Showing preview only (376K chars total). Download the full file or copy to clipboard to get everything.
Repository: venmo/slather
Branch: master
Commit: 4dba0321f81f
Files: 95
Total size: 348.6 KB
Directory structure:
gitextract_cr8xe6x0/
├── .coveralls.yml
├── .gitignore
├── .travis.yml
├── CHANGELOG.md
├── Gemfile
├── LICENSE.txt
├── README.md
├── Rakefile
├── assets/
│ ├── highlight.pack.js
│ └── slather.css
├── bin/
│ └── slather
├── lib/
│ ├── cocoapods_plugin.rb
│ ├── slather/
│ │ ├── command/
│ │ │ ├── coverage_command.rb
│ │ │ ├── setup_command.rb
│ │ │ └── version_command.rb
│ │ ├── coverage_file.rb
│ │ ├── coverage_info.rb
│ │ ├── coverage_service/
│ │ │ ├── cobertura_xml_output.rb
│ │ │ ├── coveralls.rb
│ │ │ ├── gutter_json_output.rb
│ │ │ ├── hardcover.rb
│ │ │ ├── html_output.rb
│ │ │ ├── json_output.rb
│ │ │ ├── llvm_cov_output.rb
│ │ │ ├── simple_output.rb
│ │ │ └── sonarqube_xml_output.rb
│ │ ├── coveralls_coverage.rb
│ │ ├── profdata_coverage_file.rb
│ │ ├── project.rb
│ │ └── version.rb
│ └── slather.rb
├── slather.gemspec
└── spec/
├── fixtures/
│ ├── FixtureFramework/
│ │ ├── FixtureFramework.h
│ │ ├── FlashExperiment.swift
│ │ └── Info.plist
│ ├── FixtureFrameworkTests/
│ │ ├── FixtureFrameworkTests.swift
│ │ ├── FlashExperimentTests.swift
│ │ └── Info.plist
│ ├── fixtures/
│ │ ├── Fixtures.swift
│ │ ├── Supporting Files/
│ │ │ └── fixtures-Prefix.pch
│ │ ├── fixtures.h
│ │ ├── fixtures.m
│ │ ├── fixtures_cpp.cpp
│ │ ├── fixtures_cpp.h
│ │ ├── fixtures_m.h
│ │ ├── fixtures_m.m
│ │ ├── fixtures_mm.h
│ │ ├── fixtures_mm.mm
│ │ ├── more_files/
│ │ │ ├── Branches.h
│ │ │ ├── Branches.m
│ │ │ ├── Empty.h
│ │ │ ├── Empty.m
│ │ │ ├── peekaview.h
│ │ │ └── peekaview.m
│ │ └── other_fixtures.m
│ ├── fixtures.xcodeproj/
│ │ ├── project.pbxproj
│ │ ├── project.xcworkspace/
│ │ │ └── contents.xcworkspacedata
│ │ └── xcshareddata/
│ │ └── xcschemes/
│ │ ├── aggregateFixturesTests.xcscheme
│ │ ├── fixtures.xcscheme
│ │ ├── fixturesTests.xcscheme
│ │ ├── fixturesTestsSecond.xcscheme
│ │ └── fixturesTwo.xcscheme
│ ├── fixtures.xcworkspace/
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata/
│ │ ├── IDEWorkspaceChecks.plist
│ │ └── xcschemes/
│ │ └── fixturesTestsWorkspace.xcscheme
│ ├── fixturesTests/
│ │ ├── BranchesTests.m
│ │ ├── Supporting Files/
│ │ │ ├── en.lproj/
│ │ │ │ └── InfoPlist.strings
│ │ │ └── fixturesTests-Info.plist
│ │ ├── fixturesTests.m
│ │ ├── fixturesTestsSecond.m
│ │ └── peekaviewTests💣.m
│ ├── fixturesTwo/
│ │ ├── fixturesTwo.h
│ │ └── fixturesTwo.m
│ ├── fixtures_html/
│ │ ├── Branches.m.html
│ │ ├── BranchesTests.m.html
│ │ ├── fixtures.m.html
│ │ ├── fixturesTests.m.html
│ │ ├── index.html
│ │ └── peekaviewTests💣.m.html
│ ├── gutter.json
│ └── sonarqube-generic-coverage.xml
├── slather/
│ ├── cocoapods_plugin_spec.rb
│ ├── coverage_file_spec.rb
│ ├── coverage_service/
│ │ ├── cobertura_xml_spec.rb
│ │ ├── coveralls_spec.rb
│ │ ├── gutter_json_spec.rb
│ │ ├── hardcover_spec.rb
│ │ ├── html_output_spec.rb
│ │ ├── json_spec.rb
│ │ ├── llvm_cov_spec.rb
│ │ ├── simple_output_spec.rb
│ │ └── sonarqube_xml_spec.rb
│ ├── profdata_coverage_spec.rb
│ └── project_spec.rb
└── spec_helper.rb
================================================
FILE CONTENTS
================================================
================================================
FILE: .coveralls.yml
================================================
service_name: travis-ci
================================================
FILE: .gitignore
================================================
*.gem
*.rbc
.bundle
.config
.yardoc
Gemfile.lock
InstalledFiles
_yardoc
coverage
doc/
lib/bundler/man
pkg
rdoc
spec/reports
test/tmp
test/version_tmp
tmp
*.bundle
*.so
*.o
*.a
mkmf.log
.vendor
.ruby-version
cobertura.xml
.gutter.json
html
*.gcda
*.gcno
# Xcode
#
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata
*.xccheckout
*.moved-aside
DerivedData
*.hmap
*.ipa
*.xcuserstate
*.DS_Store
# VSCode IDE
.vscode/
.rdbgrc*
# python
.venv/
# JetBrains IDE
.idea/
# Test output
report.llcov
report.json
# VSCode
.vscode
.rdbgrc*
================================================
FILE: .travis.yml
================================================
language: objective-c
script: bundle exec rake
osx_image: xcode12.2
cache: bundler
before_install:
- curl http://curl.haxx.se/ca/cacert.pem -o /usr/local/share/cacert.pem
- gem install bundler -v "~> 2.0" --no-document
install:
- bundle install --without=documentation
================================================
FILE: CHANGELOG.md
================================================
# CHANGELOG
## v2.8.5
* Update xcodeproj to 1.27.1 to support Xcode 16 folder references
[authiatr](https://github.com/authiatr)
[#574](https://github.com/SlatherOrg/slather/pull/574)
## v2.8.4
* Don't crash when 0% coverage is causing empty JSON
[jarrodlombardo-EventBase](https://github.com/jarrodlombardo-EventBase)
[#570](https://github.com/SlatherOrg/slather/pull/570)
* Xcode 16 compatibility (as of beta 5)
[ksuther](https://github.com/ksuther)
[#568](https://github.com/SlatherOrg/slather/pull/568)
## v2.8.3
* Fix coverage_file.source_file_pathname
[alfredofernandes](https://github.com/alfredofernandes)
[#565](https://github.com/SlatherOrg/slather/pull/565)
* update cobertura DTD to a working URL.
[jarrodlombardo-EventBase](https://github.com/jarrodlombardo-EventBase)
[#564](https://github.com/SlatherOrg/slather/pull/564)
## v2.8.2
* coverage_info.include_files? needs a default true return value for when source_files is empty.
[jarrodlombardo-EventBase](https://github.com/jarrodlombardo-EventBase)
[#563](https://github.com/SlatherOrg/slather/pull/563)
## v2.8.1
* cobertura.sourceforge.net should use https instead of http
[jarrodlombardo-EventBase](https://github.com/jarrodlombardo-EventBase)
[#559](https://github.com/SlatherOrg/slather/pull/559)
* Handle include globs
[dnedrow](https://github.com/dnedrow)
[#553](https://github.com/SlatherOrg/slather/pull/553)
## v2.8.0
* Add `--ymlfile` option to override `.slather.yml`
[jarrodlombardo-EventBase](https://github.com/jarrodlombardo-EventBase)
[#550](https://github.com/SlatherOrg/slather/pull/550)
* Update list.js
[AndriiZakhliupanyi](https://github.com/AndriiZakhliupanyi)
[#546](https://github.com/SlatherOrg/slather/pull/546)
## v2.7.5
* Add `--cdn-assets` flag
[sushant-here](https://github.com/sushant-here)
[#537](https://github.com/SlatherOrg/slather/pull/537)
* Update nokogiri version
## v2.7.4
* Support Ruby 3.2.0
[crazymanish](https://github.com/crazymanish)
[#532](https://github.com/SlatherOrg/slather/pull/532)
## v2.7.3
* Support Coveralls parallel runs
[paulz](https://github.com/paulz)
[#523](https://github.com/SlatherOrg/slather/pull/523)
* Update nokogiri version
[anil291987](https://github.com/anil291987)
[#518](https://github.com/SlatherOrg/slather/pull/518)
[#524](https://github.com/SlatherOrg/slather/pull/524)
## v2.7.2
* Update xcodeproj version
[adamyanalunas](https://github.com/adamyanalunas)
[#502](https://github.com/SlatherOrg/slather/pull/502)
* Update nokogiri version
[jwelton](https://github.com/jwelton)
[#503](https://github.com/SlatherOrg/slather/pull/503)
* Support alternate CI systems in coveralls output
[fermoyadrop](https://github.com/fermoyadrop)
[#504](https://github.com/SlatherOrg/slather/pull/504)
* Add Bitrise support to coveralls output
[fermoyadrop](https://github.com/fermoyadrop)
[#504](https://github.com/SlatherOrg/slather/pull/505)
## v2.7.1
* Support generating coverage for framework targets
[onato](https://github.com/onato)
[#482](https://github.com/SlatherOrg/slather/pull/482)
* Show number of lines in HTML report
[SiemianHS](https://github.com/SiemianHS)
[#494](https://github.com/SlatherOrg/slather/pull/494)
* Fixed issues with HTML report generation
[fchiba](https://github.com/fchiba)
[#483](https://github.com/SlatherOrg/slather/pull/483)
[#484](https://github.com/SlatherOrg/slather/pull/484)
* Don't fail if a source file doesn't exist
[chillpop](https://github.com/chillpop)
[#492](https://github.com/SlatherOrg/slather/pull/492)
## v2.7.0
* Add Branch Coverage data for ProfData coverage files
[hborawski](https://github.com/hborawski)
[#477](https://github.com/SlatherOrg/slather/pull/477)
* Fixed 'Argument list too long' when running 'xcrun llvm-cov'
[samuelsainz](https://github.com/samuelsainz)
[#476](https://github.com/SlatherOrg/slather/pull/476)
## v2.6.1
* Update nokogiri to 1.11
[ashin-omg](https://github.com/ashin-omg)
[#473](https://github.com/SlatherOrg/slather/pull/473)
## v2.6.0
* Added GitHub actions support
[martin-key](https://github.com/martin-key), [troyfontaine](https://github.com/troyfontaine)
[#468](https://github.com/SlatherOrg/slather/pull/468)
## v2.5.0
* Fixed activesupport and cocoapods dependencies
[daneov](https://github.com/daneov)
[#456](https://github.com/SlatherOrg/slather/pull/467)
* Fixed typo in documentation
[descorp](https://github.com/descorp)
[#456](https://github.com/SlatherOrg/slather/pull/463)
## v2.4.9
* Added support for Sonarqube output
[adellibovi](https://github.com/adellibovi)
[#456](https://github.com/SlatherOrg/slather/pull/456)
## v2.4.8
* Optimize performance for many binaries
[cltnschlosser](https://github.com/cltnschlosser)
[#455](https://github.com/SlatherOrg/slather/pull/455)
* Don't generate line 0 in profdata_coverage_file.rb from line with error
[tthbalazs](https://github.com/tthbalazs)
[#449](https://github.com/SlatherOrg/slather/pull/449)
* coveralls dependency update
[GRiMe2D](https://github.com/GRiMe2D)
[#448](https://github.com/SlatherOrg/slather/pull/448)
## v2.4.7
* Update dependencies
[dnedrow](https://github.com/dnedrow)
* Fixed errors when llvm-cov argument length exceeds ARG_MAX
[weibel](https://github.com/weibel)
[#414](https://github.com/SlatherOrg/slather/pull/414)
* Show "No coverage directory found." instead of "implicit conversion nil into String"
[phimage](https://github.com/phimage)
[#381](https://github.com/SlatherOrg/slather/pull/381) [#341](https://github.com/SlatherOrg/slather/issues/341)
## v2.4.6
* Fix .dSYM and .swiftmodule files filtering in find_binary_files()
[krin-san](https://github.com/krin-san)
[#368](https://github.com/SlatherOrg/slather/pull/368)
* Fixed loading coverage for a single source file
[blackm00n](https://github.com/blackm00n)
[#377](https://github.com/SlatherOrg/slather/pull/377) [#398](https://github.com/SlatherOrg/slather/pull/398)
* Fixed truncated file list in HTML export
[miroslavkovac](https://github.com/miroslavkovac)
[#402](https://github.com/SlatherOrg/slather/pull/402) [#261](https://github.com/SlatherOrg/slather/issues/261)
## v2.4.5
* Support for specifying a specific binary architecture
[ksuther](https://github.com/ksuther), [nickolas-pohilets](https://github.com/nickolas-pohilets)
[#367](https://github.com/SlatherOrg/slather/pull/367)
* Added absolute statement count to simple output (instead of showing just a percentage)
[barrault01](https://github.com/barrault01), [ivanbrunel](https://github.com/ivanbruel)
[#365](https://github.com/SlatherOrg/slather/pull/365)
* Updated nokogiri dependency version
[#363](https://github.com/SlatherOrg/slather/issues/363), [#366](https://github.com/SlatherOrg/slather/pull/366)
* slather now requires ruby 2.1 or later (10.13 ships with 2.3.3)
## v2.4.4
* Added llvm-cov output format
[sgtsquiggs](https://github.com/sgtsquiggs) [#354](https://github.com/SlatherOrg/slather/pull/354)
* Exclude swiftmodule from product search
[lampietti](https://github.com/lampietti) [#352](https://github.com/SlatherOrg/slather/pull/352)
## v2.4.3
* Initial Xcode 9 support
[ksuther](https://github.com/ksuther) [#339](https://github.com/SlatherOrg/slather/pull/339), [ivanbrunel](https://github.com/ivanbruel) [#321](https://github.com/SlatherOrg/slather/pull/321), [FDREAL](https://github.com/FDREAL) [#338](https://github.com/SlatherOrg/slather/pull/338)
* Add `--json` output option for basic JSON format not specific to any particular service.
[ileitch](https://github.com/ileitch)
[#318](https://github.com/SlatherOrg/slather/pull/318)
## v2.4.2
* Restored support for Xcode 7
[ButkiewiczP](https://github.com/ButkiewiczP)
[#304](https://github.com/slatherOrg/slather/pull/308)
* Added Jenkins Pipeline support for Coveralls
[daneov](https://github.com/daneov)
[#304](https://github.com/slatherOrg/slather/pull/304)
## v2.4.1
* Add `--configuration` option
[thasegaw](https://github.com/thasegaw)
[#294](https://github.com/slatherOrg/slather/pull/294)
* Fix misdetection of Xcode version if Spotlight hasn't indexed Xcode yet
[ksuther](https://github.com/ksuther)
[#298](https://github.com/slatherOrg/slather/pull/298)
* Better verbose message when no binaries are found
[ksuther](https://github.com/ksuther)
[#300](https://github.com/slatherOrg/slather/pull/300)
## v2.4.0
* Xcode 8.3 support.
[ksuther](https://github.com/ksuther)
[#291](https://github.com/SlatherOrg/slather/pull/291)
* Automatically ignore headers in Xcode platform SDKs.
[ksuther](https://github.com/ksuther)
[#286](https://github.com/SlatherOrg/slather/pull/286)
* Automatically handle schemes with multiple build or test targets
[serges147](https://github.com/serges147)
[#275](https://github.com/SlatherOrg/slather/pull/275)
* Added TeamCity as a CI service option
[joshrlesch](https://github.com/joshrlesch)
[#279](https://github.com/SlatherOrg/slather/pull/279)
* Handle UTF-8 characters correctly in HTML reports
[0xced](https://github.com/0xced)
[#259](https://github.com/SlatherOrg/slather/pull/259)
* Fix hanging `xcodebuild` invocation when getting derived data path.
[arthurtoper](https://github.com/arthurtoper)
[#238](https://github.com/SlatherOrg/slather/pull/238), [#197](https://github.com/SlatherOrg/slather/issues/197), [#212](https://github.com/SlatherOrg/slather/issues/212), [#234](https://github.com/SlatherOrg/slather/issues/234)
## v2.3.0
* Fixes broken fallback value of `input_format` inside `configure_input_format`
[sbhklr](https://github.com/sbhklr)
[#233](https://github.com/SlatherOrg/slather/pull/233), [#232](https://github.com/SlatherOrg/slather/issues/232)
* Add `--travispro` flag
[sbhklr](https://github.com/sbhklr)
[#223](https://github.com/SlatherOrg/slather/pull/223), [#219](https://github.com/SlatherOrg/slather/issues/219)
* Fixes silent failure in case of unsuccessful upload to Coveralls
[sbhklr](https://github.com/sbhklr)
[#222](https://github.com/SlatherOrg/slather/pull/222), [#217](https://github.com/SlatherOrg/slather/issues/217)
## v2.2.1
* Make `project.coverage_files` public
* Add docs attribute reader to `project.rb`
[bootstraponline](https://github.com/bootstraponline)
[#209](https://github.com/SlatherOrg/slather/pull/209)
* Add `--decimals` flag
[bootstraponline](https://github.com/bootstraponline)
[#207](https://github.com/SlatherOrg/slather/pull/207)
* Add `slather version` command
[bootstraponline](https://github.com/bootstraponline)
[#208](https://github.com/SlatherOrg/slather/pull/208)
## v2.2.0
* Fix nil crash in `project.rb` derived_data_path
[bootstraponline](https://github.com/bootstraponline)
[#203](https://github.com/SlatherOrg/slather/pull/203)
* Fix for correct line number for lines that are hit thousands or millions of time in llvm-cov.
[Mihai Parv](https://github.com/mihaiparv)
[#202](https://github.com/SlatherOrg/slather/pull/202), [#196](https://github.com/SlatherOrg/slather/issues/196)
* Generate coverate for multiple binaries by passing multiple `--binary-basename` or `--binary-file` arguments, or by using an array in `.slather.yml`
[Kent Sutherland](https://github.com/ksuther)
[#188](https://github.com/SlatherOrg/slather/pull/188)
* Support for specifying source file patterns using the `--source-files` option or the source_files key in `.slather.yml`
[Matej Bukovinski](https://github.com/matej)
[#201](https://github.com/SlatherOrg/slather/pull/201)
* Improve getting schemes. Looks for user scheme in case no shared scheme is found.
[Matyas Hlavacek](https://github.com/matyashlavacek)
[#182](https://github.com/SlatherOrg/slather/issues/182)
* Search Xcode workspaces for schemes. Workspaces are checked if no matching scheme is found in the project.
[Kent Sutherland](https://github.com/ksuther)
[#193](https://github.com/SlatherOrg/slather/pull/193), [#191](https://github.com/SlatherOrg/slather/issues/191)
* Fix for hit counts in thousands or millions being output as floats intead of integers
[Carl Hill-Popper](https://github.com/chillpop)
[#190](https://github.com/SlatherOrg/slather/pull/190)
## v2.1.0
* Support for Xcode workspaces. Define `workspace` configuration in `.slather.yml` or use the `--workspace` argument if you build in a workspace.
* Improved slather error messages
[Kent Sutherland](https://github.com/ksuther)
[#178](https://github.com/SlatherOrg/slather/issues/178)
* Re-add Teamcity support
[Boris Bügling](https://github.com/neonichu)
[#180](https://github.com/SlatherOrg/slather/pull/180)
* Show lines that are hit thousands or millions of time in llvm-cov
[Kent Sutherland](https://github.com/ksuther)
[#179](https://github.com/SlatherOrg/slather/pull/179)
* Fix for setting scheme/workspace from configuration file.
[Boris Bügling](https://github.com/neonichu)
[#183](https://github.com/SlatherOrg/slather/pull/183)
## v2.0.2
* Escape the link to file names properly
[Thomas Mellenthin](https://github.com/melle)
[#158](https://github.com/SlatherOrg/slather/pull/158)
* Product info is now read from schemes. Specify a scheme in `.slather.yml` or with the `--scheme` argument to ensure consistent results. Automatically detect the derived data directory from `xcodebuild`
[Kent Sutherland](https://github.com/ksuther)
[#174](https://github.com/SlatherOrg/slather/pull/174)
* Xcode 7.3 compatibility (updated path returned by `profdata_coverage_dir`)
[Kent Sutherland](https://github.com/ksuther)
[#125](https://github.com/SlatherOrg/slather/issues/125), [#169](https://github.com/SlatherOrg/slather/pull/169)
* Improve matching of xctest bundles when using `--binary-basename`
[Kent Sutherland](https://github.com/ksuther)
[#167](https://github.com/SlatherOrg/slather/pull/167)
* Build Statistic Reporting for TeamCity
[Michael Myers](https://github.com/michaelmyers)
[#150](https://github.com/SlatherOrg/slather/pull/150)
* Use named classes for subcommands in bin/slather
[bootstraponline](https://github.com/bootstraponline)
[#170](https://github.com/SlatherOrg/slather/pull/170)
## v2.0.1
* Fixes how `profdata_coverage_dir` is created.
[guidomb](https://github.com/guidomb)
[#145](https://github.com/SlatherOrg/slather/pull/145)
## v2.0.0
* Correct html rendering when using profdata format
[cutz](https://github.com/cutz)
[#124](https://github.com/SlatherOrg/slather/pull/124)
* Making HTML directory self contained
[Colin Cornaby](https://github.com/colincornaby)
[#137](https://github.com/SlatherOrg/slather/pull/137)
* Add `binary_basename` configuration option
[Boris Bügling](https://github.com/neonichu)
[#128](https://github.com/SlatherOrg/slather/pull/128)
* Add support to profdata file format
[Simone Civetta](https://github.com/viteinfinite)
[Olivier Halligon](https://github.com/AliSoftware)
[Matt Delves](https://github.com/mattdelves)
[Pierre-Marc Airoldi](https://github.com/petester42)
[#92](https://github.com/venmo/slather/pull/92)
## v1.8.3
* Add buildkite support to coveralls
[David Hardiman](https://github.com/dhardiman)
[#98](https://github.com/venmo/slather/pull/98)
* Update to xcodeproj 0.28.0 to avoid collisions with Cocoapods 0.39.0
[Julian Krumow](https://github.com/tarbrain)
[#106](https://github.com/venmo/slather/pull/106)/[#109](https://github.com/venmo/slather/pull/109)
## v1.8.1
* Fixed dependency conflict with CocoaPods v0.38
* Updated usage of cocoapods plugin API since it has changed in v0.38
[Julian Krumow](https://github.com/tarbrain)
[#95](https://github.com/venmo/slather/pull/95)
## v1.7.0
* Objective-C++ support
[ben-ng](https://github.com/ben-ng)
[#63](https://github.com/venmo/slather/pull/63)
## v1.6.0
* Add CircleCI support
[Jonathan Hersh](https://github.com/jhersh)
[#55](https://github.com/venmo/slather/pull/55)
## v1.5.4
* Fix calculation of branch coverage when a class has no branches
[Julian Krumow](https://github.com/tarbrain)
[#40](https://github.com/venmo/slather/pull/40)
* Always consider empty files as 100% tested
[Boris Bügling](https://github.com/neonichu)
[#45](https://github.com/venmo/slather/pull/45)
## v1.5.2
* Add an option to define the output directory for cobertura xml reports
[Julian Krumow](https://github.com/tarbrain)
[#37](https://github.com/venmo/slather/pull/37)
## v1.5.1
* Avoid crashes when coverage data is empty
* Fix bug which prevented source files without coverage data to be included in Cobertura xml report
[Julian Krumow](https://github.com/tarbrain)
[#34](https://github.com/venmo/slather/pull/34)
## v1.5.0
* Add support for Cobertura
[Julian Krumow](https://github.com/tarbrain)
[#30](https://github.com/venmo/slather/pull/30)
## v1.4.0
* Implement a CocoaPods plugin
[Kyle Fuller](https://github.com/kylef)
[#25](https://github.com/venmo/slather/pull/25)
* Avoid getting 'Infinity' or 'NaN' when dividing by 0.0
[Mark Larsen](https://github.com/marklarr)
* Ignore exceptions about files not existing by using 'force'
[Mark Larsen](https://github.com/marklarr)
## v1.3.0
* Add Gutter JSON output
[Boris Bügling](https://github.com/neonichu)
[#24](https://github.com/venmo/slather/pull/24)
## v1.2.1
* Fix typo --simple-output description
[Ayaka Nonaka](https://github.com/ayanonagon)
[#19](https://github.com/venmo/slather/pull/19)
* Remove broken travis pro support
[Mark Larsen](https://github.com/marklarr)
[#22](https://github.com/venmo/slather/pull/22)
* Fix exception for files without `@interface` or `@implementation`
[Piet Brauer](https://github.com/pietbrauer)
[#23](https://github.com/venmo/slather/pull/23)
## v1.2.0
* Remove duplicate coverage files, favoring the file with higher coverage.
[Ayaka Nonaka](https://github.com/ayanonagon)
[#16](https://github.com/venmo/slather/pull/16)
* Add support for access token and Travis Pro
[Chris Maddern](https://github.com/chrismaddern)
[#17](https://github.com/venmo/slather/pull/17)
## v1.1.0
* Support for code coverage of pods
[Mark Larsen](https://github.com/marklarr)
## v1.0.1
* Fix coverage search for files that contain spaces
[Mark Larsen](https://github.com/marklarr)
## v1.0.0
* beautified README
[Ayaka Nonaka](https://github.com/ayanonagon)
[#4](https://github.com/venmo/slather/pull/4)
[Kyle Fuller](https://github.com/kylef)
[#5](https://github.com/venmo/slather/pull/5)
* Add Travis automated builds
[Mark Larsen](https://github.com/marklarr)
[#6](https://github.com/venmo/slather/pull/6)
* Use `||=` instead of `unless`
[Ayaka Nonaka](https://github.com/ayanonagon)
[#7](https://github.com/venmo/slather/pull/7)
## v0.0.31
* find source files via pbx proj rather than file system
[Mark Larsen](https://github.com/marklarr)
## v0.0.3
* Initial Release
[Mark Larsen](https://github.com/marklarr)
================================================
FILE: Gemfile
================================================
source 'https://rubygems.org'
# Specify your gem's dependencies in slather.gemspec
gemspec
================================================
FILE: LICENSE.txt
================================================
Copyright (c) 2014 Mark Larsen
MIT License
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
================================================
FILE: README.md
================================================

[](http://badge.fury.io/rb/slather)
[](https://travis-ci.org/SlatherOrg/slather)
[](https://coveralls.io/r/SlatherOrg/slather?branch=master)
Generate test coverage reports for Xcode projects & hook it into CI.
### Projects that use Slather
| Project | Coverage |
| ------- |:--------:|
| [Parsimmon](https://github.com/ayanonagon/Parsimmon) | [](https://coveralls.io/r/ayanonagon/Parsimmon?branch=master) |
| [VENCore](https://github.com/venmo/VENCore) | [](https://coveralls.io/r/venmo/VENCore?branch=master) |
| [DAZABTest](https://github.com/dasmer/DAZABTest) | [](https://coveralls.io/r/dasmer/DAZABTest?branch=master) |
| [TBStateMachine](https://github.com/tarbrain/TBStateMachine) | [](https://coveralls.io/r/tarbrain/TBStateMachine?branch=master) |
## Installation
Add this line to your application's Gemfile:
```ruby
gem 'slather'
```
And then execute:
```sh
$ bundle
```
Or install the gem:
```sh
gem install slather
```
## Usage
Enable test coverage by ticking the *"Gather coverage data"* checkbox when editing a scheme:

To verify you're ready to generate test coverage, run your test suite on your project, and then run:
```sh
$ slather coverage -s --scheme YourXcodeSchemeName path/to/project.xcodeproj
```
If you use a workspace in Xcode you need to specify it:
```sh
$ slather coverage -s --scheme YourXcodeSchemeName --workspace path/to/workspace.xcworkspace path/to/project.xcodeproj
```
If you use a different configuration for your tests:
```sh
$ slather coverage -s --scheme YourXcodeSchemeName --configuration YourBuildConfigurationName path/to/project.xcodeproj
```
If your configuration produces a universal binary you need to specify a specific architecture to use:
```sh
$ slather coverage -s --arch x86_64 --scheme YourXcodeSchemeName --configuration YourBuildConfigurationName path/to/project.xcodeproj
```
### For multiple modules
If you want to run some modules, but not all (like modules created by CocoaPods) you can do it like this:
```sh
$ slather coverage --binary-basename module1 --binary-basename module2 path/to/project.xcodeproj
```
You can also add it to the `.slather.yml` file as an array:
```yml
binary_basename:
- module1
- module2
```
### Setup for Xcode 5 and 6
Run this command to enable the `Generate Test Coverage` and `Instrument Program Flow` flags for your project:
```sh
$ slather setup path/to/project.xcodeproj
```
## General Usage Notes
### Commandline Arguments Win
When using both a config file (`.slather.yml`) and providing arguments via the commandline,
the arguments will take precedence over the matching setting in the config file.
### `ignore` always wins over `source-files`
When defining both files that should be ignored (`--ignore`, ignore) and source files to include (`--source-files`, source_files),
the ignore list is checked first. If the file being scanned matches a glob in the ignore list, it will not be included. In this case, the
source_file list is not checked.
If the file being scanned is not in the ignore list, and source_file has been defined, the source_file list is
checked. If the source file matches a glob, it will be included.
## CI Integration
### Usage with Codecov
Login to [Codecov](https://codecov.io/) (no need to activate a repository, this happens automatically). Right now, `slather` supports Codecov via **all** supported CI providers [listed here](https://github.com/codecov/codecov-bash#ci-providers).
Make a `.slather.yml` file:
```yml
# .slather.yml
coverage_service: cobertura_xml
xcodeproj: path/to/project.xcodeproj
scheme: YourXcodeSchemeName
configuration: TestedConfiguration
source_directory: path/to/sources/to/include
output_directory: path/to/xml_report
ignore:
- ExamplePodCode/*
- ProjectTestsGroup/*
```
And then in your `.travis.yml`, `circle.yml` (or after test commands in other CI providers), call `slather` after a successful build:
```yml
# .travis.yml
before_install: rvm use $RVM_RUBY_VERSION
install: bundle install --without=documentation --path ../travis_bundle_dir
after_success:
- slather
- bash <(curl -s https://codecov.io/bash) -f path/to/xml_report/cobertura.xml -X coveragepy -X gcov -X xcode
```
```yml
# circle.yml
test:
post:
- bundle exec slather
- bash <(curl -s https://codecov.io/bash) -f path/to/xml_report/cobertura.xml -X coveragepy -X gcov -X xcode
```
> Private repo? Add `-t :uuid-repo-token` to the codecov uploader. Read more about uploading report to Codecov [here](https://github.com/codecov/codecov-bash)
### Usage with Coveralls
Login to [Coveralls](https://coveralls.io/) and enable your repository. Right now, `slather` supports Coveralls via [Travis CI](https://travis-ci.org), [CircleCI](https://circleci.com), [Jenkins](https://www.jenkins.io/), [Teamcity](https://www.jetbrains.com/teamcity/), [Buildkite](https://buildkite.com/), and [Bitrise](https://bitrise.io/).
Make a `.slather.yml` file and specify the CI Service you're using:
```yml
# .slather.yml
ci_service: circleci | travis_ci | travis_pro | jenkins | buildkite | teamcity
coverage_service: coveralls
xcodeproj: path/to/project.xcodeproj
scheme: YourXcodeSchemeName
ignore:
- ExamplePodCode/*
- ProjectTestsGroup/*
```
And then in your `.travis.yml` or `circle.yml` or `github-action.yml`, call `slather` after a successful build:
```yml
# .travis.yml
before_install: rvm use $RVM_RUBY_VERSION
install: bundle install --without=documentation --path ../travis_bundle_dir
after_success: slather
```
```yml
# circle.yml
test:
post:
- bundle exec slather
```
```yml
# github-action.yml
myjob:
steps:
- run: |
bundle config path vendor/bundle
bundle install --without=documentation --jobs 4 --retry 3
- name: Extract branch name
shell: bash
run: echo "##[set-output name=branch;]$(echo ${GITHUB_REF#refs/heads/})"
id: get_branch
- run: bundle exec slather
env:
GIT_BRANCH: ${{ steps.get_branch.outputs.branch }}
CI_PULL_REQUEST: ${{ github.event.number }}
COVERAGE_ACCESS_TOKEN: ${{ secrets.GITHUB_TOKEN }}
```
#### Usage with Travis CI Pro
To use Coveralls with Travis CI Pro (for private repos), add following lines along with other settings to `.slather.yml`:
```yml
# .slather.yml
ci_service: travis_pro
coverage_access_token: <YOUR ACCESS TOKEN>
```
The coverage token can be found at [Coveralls](https://coveralls.io/) repo page. Or it can be passed in via the `COVERAGE_ACCESS_TOKEN` environment var.
### Cobertura
To create a Cobertura XML report set `cobertura_xml` as coverage service inside your `.slather.yml`. Optionally you can define an output directory for the XML report:
```yml
# .slather.yml
coverage_service: cobertura_xml
xcodeproj: path/to/project.xcodeproj
scheme: YourXcodeSchemeName
source_directory: path/to/sources/to/include
output_directory: path/to/xml_report
ignore:
- ExamplePodCode/*
- ProjectTestsGroup/*
```
Or use the command line options `--cobertura-xml` or `-x` and `--output-directory`:
```sh
$ slather coverage -x --output-directory path/to/xml_report
```
### Static HTML
To create a report as static html pages, use the command line options `--html`:
```sh
$ slather coverage --html --scheme YourXcodeSchemeName path/to/project.xcodeproj
```
This will make a directory named `html` in your root directory (unless `--output-directory` is specified) and will generate all the reports as static html pages inside the directory. It will print out the report's path by default, but you can also specify `--show` flag to open it in your browser automatically.
By default, the generated HTML will reference locally hosted assets (js, css). You can specify the `--cdn-assets` to specify that you prefer for the generated HTML to use externally hosted assets. This can be useful if publishing the HTML file as a build artifact.
### TeamCity Reporting
To report the coverage statistics to TeamCity:
```sh
$ slather coverage --teamcity -s --scheme YourXcodeSchemeName
```
### Coverage for code included via CocoaPods
If you're trying to compute the coverage of code that has been included via
CocoaPods, you will need to tell CocoaPods to use the Slather plugin by
adding the following to your `Podfile`.
```ruby
plugin 'slather'
```
You will also need to tell Slather where to find the source files for your Pod.
```yml
# .slather.yml
source_directory: Pods/AFNetworking
```
### Custom Build Directory
Slather will look for the test coverage files in `DerivedData` by default. If you send build output to a custom location, like [this](https://github.com/erikdoe/ocmock/blob/7f4d22b38eedf1bb9a12ab1591ac0a5d436db61a/Tools/travis.sh#L12), then you should also set the `build_directory` property in `.slather.yml`
### Building in a workspace
Include the `--workspace` argument or add `workspace` to `.slather.yml` if you build your project in a workspace. For example:
```sh
$ slather coverage --html --scheme YourXcodeSchemeName --workspace path/to/workspace.xcworkspace path/to/project.xcodeproj
```
## Contributing
We’d love to see your ideas for improving this library! The best way to contribute is by submitting a pull request. We’ll do our best to respond to your patch as soon as possible. You can also submit a [new GitHub issue](https://github.com/SlatherOrg/slather/issues/new) if you find bugs or have questions. :octocat:
Please make sure to follow our general coding style and add test coverage for new features!
## Contributors
* [@tpoulos](https://github.com/tpoulos), the perfect logo.
* [@ayanonagon](https://github.com/ayanonagon) and [@kylef](https://github.com/kylef), feedback and testing.
* [@jhersh](https://github.com/jhersh), CircleCI support.
* [@tarbrain](https://github.com/tarbrain), Cobertura support and bugfixing.
* [@ikhsan](https://github.com/ikhsan), html support.
* [@martin-key](https://github.com/martin-key) and [@troyfontaine](https://github.com/troyfontaine), Github Actions support.
================================================
FILE: Rakefile
================================================
require "bundler/gem_tasks"
require "rspec/core/rake_task"
RSpec::Core::RakeTask.new(:spec)
task default: :spec
================================================
FILE: assets/highlight.pack.js
================================================
!function(e){"undefined"!=typeof exports?e(exports):(window.hljs=e({}),"function"==typeof define&&define.amd&&define("hljs",[],function(){return window.hljs}))}(function(e){function n(e){return e.replace(/&/gm,"&").replace(/</gm,"<").replace(/>/gm,">")}function t(e){return e.nodeName.toLowerCase()}function r(e,n){var t=e&&e.exec(n);return t&&0==t.index}function a(e){return/no-?highlight|plain|text/.test(e)}function i(e){var n,t,r,i=e.className+" ";if(i+=e.parentNode?e.parentNode.className:"",t=/\blang(?:uage)?-([\w-]+)\b/.exec(i))return E(t[1])?t[1]:"no-highlight";for(i=i.split(/\s+/),n=0,r=i.length;r>n;n++)if(E(i[n])||a(i[n]))return i[n]}function o(e,n){var t,r={};for(t in e)r[t]=e[t];if(n)for(t in n)r[t]=n[t];return r}function u(e){var n=[];return function r(e,a){for(var i=e.firstChild;i;i=i.nextSibling)3==i.nodeType?a+=i.nodeValue.length:1==i.nodeType&&(n.push({event:"start",offset:a,node:i}),a=r(i,a),t(i).match(/br|hr|img|input/)||n.push({event:"stop",offset:a,node:i}));return a}(e,0),n}function c(e,r,a){function i(){return e.length&&r.length?e[0].offset!=r[0].offset?e[0].offset<r[0].offset?e:r:"start"==r[0].event?e:r:e.length?e:r}function o(e){function r(e){return" "+e.nodeName+'="'+n(e.value)+'"'}f+="<"+t(e)+Array.prototype.map.call(e.attributes,r).join("")+">"}function u(e){f+="</"+t(e)+">"}function c(e){("start"==e.event?o:u)(e.node)}for(var s=0,f="",l=[];e.length||r.length;){var g=i();if(f+=n(a.substr(s,g[0].offset-s)),s=g[0].offset,g==e){l.reverse().forEach(u);do c(g.splice(0,1)[0]),g=i();while(g==e&&g.length&&g[0].offset==s);l.reverse().forEach(o)}else"start"==g[0].event?l.push(g[0].node):l.pop(),c(g.splice(0,1)[0])}return f+n(a.substr(s))}function s(e){function n(e){return e&&e.source||e}function t(t,r){return new RegExp(n(t),"m"+(e.cI?"i":"")+(r?"g":""))}function r(a,i){if(!a.compiled){if(a.compiled=!0,a.k=a.k||a.bK,a.k){var u={},c=function(n,t){e.cI&&(t=t.toLowerCase()),t.split(" ").forEach(function(e){var t=e.split("|");u[t[0]]=[n,t[1]?Number(t[1]):1]})};"string"==typeof a.k?c("keyword",a.k):Object.keys(a.k).forEach(function(e){c(e,a.k[e])}),a.k=u}a.lR=t(a.l||/\b\w+\b/,!0),i&&(a.bK&&(a.b="\\b("+a.bK.split(" ").join("|")+")\\b"),a.b||(a.b=/\B|\b/),a.bR=t(a.b),a.e||a.eW||(a.e=/\B|\b/),a.e&&(a.eR=t(a.e)),a.tE=n(a.e)||"",a.eW&&i.tE&&(a.tE+=(a.e?"|":"")+i.tE)),a.i&&(a.iR=t(a.i)),void 0===a.r&&(a.r=1),a.c||(a.c=[]);var s=[];a.c.forEach(function(e){e.v?e.v.forEach(function(n){s.push(o(e,n))}):s.push("self"==e?a:e)}),a.c=s,a.c.forEach(function(e){r(e,a)}),a.starts&&r(a.starts,i);var f=a.c.map(function(e){return e.bK?"\\.?("+e.b+")\\.?":e.b}).concat([a.tE,a.i]).map(n).filter(Boolean);a.t=f.length?t(f.join("|"),!0):{exec:function(){return null}}}}r(e)}function f(e,t,a,i){function o(e,n){for(var t=0;t<n.c.length;t++)if(r(n.c[t].bR,e))return n.c[t]}function u(e,n){if(r(e.eR,n)){for(;e.endsParent&&e.parent;)e=e.parent;return e}return e.eW?u(e.parent,n):void 0}function c(e,n){return!a&&r(n.iR,e)}function g(e,n){var t=N.cI?n[0].toLowerCase():n[0];return e.k.hasOwnProperty(t)&&e.k[t]}function h(e,n,t,r){var a=r?"":w.classPrefix,i='<span class="'+a,o=t?"":"</span>";return i+=e+'">',i+n+o}function p(){if(!L.k)return n(B);var e="",t=0;L.lR.lastIndex=0;for(var r=L.lR.exec(B);r;){e+=n(B.substr(t,r.index-t));var a=g(L,r);a?(y+=a[1],e+=h(a[0],n(r[0]))):e+=n(r[0]),t=L.lR.lastIndex,r=L.lR.exec(B)}return e+n(B.substr(t))}function d(){if(L.sL&&!x[L.sL])return n(B);var e=L.sL?f(L.sL,B,!0,M[L.sL]):l(B);return L.r>0&&(y+=e.r),"continuous"==L.subLanguageMode&&(M[L.sL]=e.top),h(e.language,e.value,!1,!0)}function b(){return void 0!==L.sL?d():p()}function v(e,t){var r=e.cN?h(e.cN,"",!0):"";e.rB?(k+=r,B=""):e.eB?(k+=n(t)+r,B=""):(k+=r,B=t),L=Object.create(e,{parent:{value:L}})}function m(e,t){if(B+=e,void 0===t)return k+=b(),0;var r=o(t,L);if(r)return k+=b(),v(r,t),r.rB?0:t.length;var a=u(L,t);if(a){var i=L;i.rE||i.eE||(B+=t),k+=b();do L.cN&&(k+="</span>"),y+=L.r,L=L.parent;while(L!=a.parent);return i.eE&&(k+=n(t)),B="",a.starts&&v(a.starts,""),i.rE?0:t.length}if(c(t,L))throw new Error('Illegal lexeme "'+t+'" for mode "'+(L.cN||"<unnamed>")+'"');return B+=t,t.length||1}var N=E(e);if(!N)throw new Error('Unknown language: "'+e+'"');s(N);var R,L=i||N,M={},k="";for(R=L;R!=N;R=R.parent)R.cN&&(k=h(R.cN,"",!0)+k);var B="",y=0;try{for(var C,j,I=0;;){if(L.t.lastIndex=I,C=L.t.exec(t),!C)break;j=m(t.substr(I,C.index-I),C[0]),I=C.index+j}for(m(t.substr(I)),R=L;R.parent;R=R.parent)R.cN&&(k+="</span>");return{r:y,value:k,language:e,top:L}}catch(O){if(-1!=O.message.indexOf("Illegal"))return{r:0,value:n(t)};throw O}}function l(e,t){t=t||w.languages||Object.keys(x);var r={r:0,value:n(e)},a=r;return t.forEach(function(n){if(E(n)){var t=f(n,e,!1);t.language=n,t.r>a.r&&(a=t),t.r>r.r&&(a=r,r=t)}}),a.language&&(r.second_best=a),r}function g(e){return w.tabReplace&&(e=e.replace(/^((<[^>]+>|\t)+)/gm,function(e,n){return n.replace(/\t/g,w.tabReplace)})),w.useBR&&(e=e.replace(/\n/g,"<br>")),e}function h(e,n,t){var r=n?R[n]:t,a=[e.trim()];return e.match(/\bhljs\b/)||a.push("hljs"),-1===e.indexOf(r)&&a.push(r),a.join(" ").trim()}function p(e){var n=i(e);if(!a(n)){var t;w.useBR?(t=document.createElementNS("http://www.w3.org/1999/xhtml","div"),t.innerHTML=e.innerHTML.replace(/\n/g,"").replace(/<br[ \/]*>/g,"\n")):t=e;var r=t.textContent,o=n?f(n,r,!0):l(r),s=u(t);if(s.length){var p=document.createElementNS("http://www.w3.org/1999/xhtml","div");p.innerHTML=o.value,o.value=c(s,u(p),r)}o.value=g(o.value),e.innerHTML=o.value,e.className=h(e.className,n,o.language),e.result={language:o.language,re:o.r},o.second_best&&(e.second_best={language:o.second_best.language,re:o.second_best.r})}}function d(e){w=o(w,e)}function b(){if(!b.called){b.called=!0;var e=document.querySelectorAll("pre code");Array.prototype.forEach.call(e,p)}}function v(){addEventListener("DOMContentLoaded",b,!1),addEventListener("load",b,!1)}function m(n,t){var r=x[n]=t(e);r.aliases&&r.aliases.forEach(function(e){R[e]=n})}function N(){return Object.keys(x)}function E(e){return x[e]||x[R[e]]}var w={classPrefix:"hljs-",tabReplace:null,useBR:!1,languages:void 0},x={},R={};return e.highlight=f,e.highlightAuto=l,e.fixMarkup=g,e.highlightBlock=p,e.configure=d,e.initHighlighting=b,e.initHighlightingOnLoad=v,e.registerLanguage=m,e.listLanguages=N,e.getLanguage=E,e.inherit=o,e.IR="[a-zA-Z]\\w*",e.UIR="[a-zA-Z_]\\w*",e.NR="\\b\\d+(\\.\\d+)?",e.CNR="\\b(0[xX][a-fA-F0-9]+|(\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",e.BNR="\\b(0b[01]+)",e.RSR="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",e.BE={b:"\\\\[\\s\\S]",r:0},e.ASM={cN:"string",b:"'",e:"'",i:"\\n",c:[e.BE]},e.QSM={cN:"string",b:'"',e:'"',i:"\\n",c:[e.BE]},e.PWM={b:/\b(a|an|the|are|I|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such)\b/},e.C=function(n,t,r){var a=e.inherit({cN:"comment",b:n,e:t,c:[]},r||{});return a.c.push(e.PWM),a.c.push({cN:"doctag",bK:"TODO FIXME NOTE BUG XXX",r:0}),a},e.CLCM=e.C("//","$"),e.CBCM=e.C("/\\*","\\*/"),e.HCM=e.C("#","$"),e.NM={cN:"number",b:e.NR,r:0},e.CNM={cN:"number",b:e.CNR,r:0},e.BNM={cN:"number",b:e.BNR,r:0},e.CSSNM={cN:"number",b:e.NR+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",r:0},e.RM={cN:"regexp",b:/\//,e:/\/[gimuy]*/,i:/\n/,c:[e.BE,{b:/\[/,e:/\]/,r:0,c:[e.BE]}]},e.TM={cN:"title",b:e.IR,r:0},e.UTM={cN:"title",b:e.UIR,r:0},e});hljs.registerLanguage("json",function(e){var t={literal:"true false null"},i=[e.QSM,e.CNM],l={cN:"value",e:",",eW:!0,eE:!0,c:i,k:t},c={b:"{",e:"}",c:[{cN:"attribute",b:'\\s*"',e:'"\\s*:\\s*',eB:!0,eE:!0,c:[e.BE],i:"\\n",starts:l}],i:"\\S"},n={b:"\\[",e:"\\]",c:[e.inherit(l,{cN:null})],i:"\\S"};return i.splice(i.length,0,c,n),{c:i,k:t,i:"\\S"}});hljs.registerLanguage("objectivec",function(e){var t={cN:"built_in",b:"(AV|CA|CF|CG|CI|MK|MP|NS|UI)\\w+"},i={keyword:"int float while char export sizeof typedef const struct for union unsigned long volatile static bool mutable if do return goto void enum else break extern asm case short default double register explicit signed typename this switch continue wchar_t inline readonly assign readwrite self @synchronized id typeof nonatomic super unichar IBOutlet IBAction strong weak copy in out inout bycopy byref oneway __strong __weak __block __autoreleasing @private @protected @public @try @property @end @throw @catch @finally @autoreleasepool @synthesize @dynamic @selector @optional @required",literal:"false true FALSE TRUE nil YES NO NULL",built_in:"BOOL dispatch_once_t dispatch_queue_t dispatch_sync dispatch_async dispatch_once"},o=/[a-zA-Z@][a-zA-Z0-9_]*/,n="@interface @class @protocol @implementation";return{aliases:["mm","objc","obj-c"],k:i,l:o,i:"</",c:[t,e.CLCM,e.CBCM,e.CNM,e.QSM,{cN:"string",v:[{b:'@"',e:'"',i:"\\n",c:[e.BE]},{b:"'",e:"[^\\\\]'",i:"[^\\\\][^']"}]},{cN:"preprocessor",b:"#",e:"$",c:[{cN:"title",v:[{b:'"',e:'"'},{b:"<",e:">"}]}]},{cN:"class",b:"("+n.split(" ").join("|")+")\\b",e:"({|$)",eE:!0,k:n,l:o,c:[e.UTM]},{cN:"variable",b:"\\."+e.UIR,r:0}]}});hljs.registerLanguage("cpp",function(t){var e={cN:"keyword",b:"[a-z\\d_]*_t"},r={keyword:"false int float while private char catch export virtual operator sizeof dynamic_cast|10 typedef const_cast|10 const struct for static_cast|10 union namespace unsigned long volatile static protected bool template mutable if public friend do goto auto void enum else break extern using true class asm case typeid short reinterpret_cast|10 default double register explicit signed typename try this switch continue inline delete alignof constexpr decltype noexcept nullptr static_assert thread_local restrict _Bool complex _Complex _Imaginary atomic_bool atomic_char atomic_schar atomic_uchar atomic_short atomic_ushort atomic_int atomic_uint atomic_long atomic_ulong atomic_llong atomic_ullong",built_in:"std string cin cout cerr clog stringstream istringstream ostringstream auto_ptr deque list queue stack vector map set bitset multiset multimap unordered_set unordered_map unordered_multiset unordered_multimap array shared_ptr abort abs acos asin atan2 atan calloc ceil cosh cos exit exp fabs floor fmod fprintf fputs free frexp fscanf isalnum isalpha iscntrl isdigit isgraph islower isprint ispunct isspace isupper isxdigit tolower toupper labs ldexp log10 log malloc memchr memcmp memcpy memset modf pow printf putchar puts scanf sinh sin snprintf sprintf sqrt sscanf strcat strchr strcmp strcpy strcspn strlen strncat strncmp strncpy strpbrk strrchr strspn strstr tanh tan vfprintf vprintf vsprintf"};return{aliases:["c","cc","h","c++","h++","hpp"],k:r,i:"</",c:[e,t.CLCM,t.CBCM,{cN:"string",v:[t.inherit(t.QSM,{b:'((u8?|U)|L)?"'}),{b:'(u8?|U)?R"',e:'"',c:[t.BE]},{b:"'\\\\?.",e:"'",i:"."}]},{cN:"number",b:"\\b(\\d+(\\.\\d*)?|\\.\\d+)(u|U|l|L|ul|UL|f|F)"},t.CNM,{cN:"preprocessor",b:"#",e:"$",k:"if else elif endif define undef warning error line pragma",c:[{b:/\\\n/,r:0},{b:'include\\s*[<"]',e:'[>"]',k:"include",i:"\\n"},t.CLCM]},{b:"\\b(deque|list|queue|stack|vector|map|set|bitset|multiset|multimap|unordered_map|unordered_set|unordered_multiset|unordered_multimap|array)\\s*<",e:">",k:r,c:["self",e]},{b:t.IR+"::",k:r},{bK:"new throw return else",r:0},{cN:"function",b:"("+t.IR+"\\s+)+"+t.IR+"\\s*\\(",rB:!0,e:/[{;=]/,eE:!0,k:r,c:[{b:t.IR+"\\s*\\(",rB:!0,c:[t.TM],r:0},{cN:"params",b:/\(/,e:/\)/,k:r,r:0,c:[t.CBCM]},t.CLCM,t.CBCM]}]}});
================================================
FILE: assets/slather.css
================================================
/* --------------------------------------------------------
Slather stylesheet
version: 0.1
author: Ikhsan Assaat (@ixnixnixn)
----------------------------------------------------------*/
/* General */
html {
position: relative;
min-height: 100%;
}
body {
font: 16px "Helvetica", sans-serif;
margin: 0 0 120px;
color: #333;
}
.row { margin: 0 2em; }
/* Header */
header { margin-top: 1em; }
header img { width: auto; height: 120px; }
/* Coverage */
#reports > h2 { margin-bottom: 0; }
#reports > h4 { margin-top: 5px; }
.percentage {
padding: 4px ;
font-weight: bold;
}
.cov_high { color: #67CF7C; }
.cov_medium { color: #F89404; }
.cov_low { color: #F86769; }
.cov_title { margin-bottom: 0; }
.cov_subtitle { margin-top: 0.2em; }
.cov_filepath { font-style: italic; }
/* Index Table */
table.coverage_list {
width: 90%;
min-width: 400px;
}
table.coverage_list th,
table.coverage_list td {
padding: .6em .5em;
text-align: left;
}
table.coverage_list th.col_num { width: 70px; }
table.coverage_list th.col_percent { width: 75px; }
table.coverage_list thead, tfoot { background: #FDCD9B; }
table.coverage_list tbody tr:hover { background: #FCF2E6; }
table.coverage_list tbody td { border-bottom: 1px solid #CCC; }
table.coverage_list td a {
color: #333;
text-decoration: none;
border-bottom: 1px dotted;
}
table.coverage_list td a:hover {
border-bottom: none;
}
/* Source Code */
table.source_code {
width: 100%;
max-width: 1200px;
min-width: 400px;
font-size: 13px;
border-spacing: 0;
background: #FCF2E6;
padding: 1.2em 1em;
margin-bottom: 2em;
}
table.source_code td {
padding-bottom: 0.3em;
}
code.missed { background-color: rgba(255, 73, 76, 0.3); }
table.source_code tr.missed td { background-color: rgba(248, 103, 105, 0.2); }
table.source_code tr.covered td { background-color: rgba(103, 207, 124, 0.2); }
table.source_code td.num {
border-right: 1px rgba(0,0,0,0.1) solid;
text-align: right;
padding-right: 1em;
width: 30px;
}
table.source_code td.src {
border-left: 1px rgba(255,255,255,0.7) solid;
padding-left: 1em;
}
table.source_code td.src pre {
white-space: pre-wrap;
white-space: -moz-pre-wrap;
white-space: -pre-wrap;
white-space: -o-pre-wrap;
word-wrap: break-word;
margin: 0;
}
table.source_code td.src pre code { font: 13px "Menlo", "Courier New"; }
table.source_code td.coverage {
text-align: right;
padding-right: 0.5em;
}
/* Footer */
footer {
background-color: #67CDCF;
height: 80px;
position: absolute;
left: 0;
bottom: 0;
width: 100%;
overflow:hidden;
}
footer p, footer a {
color: #ffffff;
font-weight: bold;
text-align: center;
}
/* ----------------------------------------------------------
Syntax Highlighting using highlight.js (https://highlightjs.org)
------------------------------------------------------------- */
.hljs {
display: inline-block;
overflow-x: auto;
-webkit-text-size-adjust: none;
}
.hljs,
.hljs-subst,
.hljs-tag .hljs-title,
.nginx .hljs-title {
color: #333;
}
.hljs-string,
.hljs-title,
.hljs-constant,
.hljs-parent,
.hljs-tag .hljs-value,
.hljs-rule .hljs-value,
.hljs-preprocessor,
.hljs-pragma,
.hljs-name,
.haml .hljs-symbol,
.ruby .hljs-symbol,
.ruby .hljs-symbol .hljs-string,
.hljs-template_tag,
.django .hljs-variable,
.smalltalk .hljs-class,
.hljs-addition,
.hljs-flow,
.hljs-stream,
.bash .hljs-variable,
.pf .hljs-variable,
.apache .hljs-tag,
.apache .hljs-cbracket,
.tex .hljs-command,
.tex .hljs-special,
.erlang_repl .hljs-function_or_atom,
.asciidoc .hljs-header,
.markdown .hljs-header,
.coffeescript .hljs-attribute,
.tp .hljs-variable {
color: #D14F4F;
}
.smartquote,
.hljs-comment,
.hljs-annotation,
.diff .hljs-header,
.hljs-chunk,
.asciidoc .hljs-blockquote,
.markdown .hljs-blockquote {
color: #888;
}
.hljs-number,
.hljs-date,
.hljs-regexp,
.hljs-literal,
.hljs-hexcolor,
.smalltalk .hljs-symbol,
.smalltalk .hljs-char,
.go .hljs-constant,
.hljs-change,
.lasso .hljs-variable,
.makefile .hljs-variable,
.asciidoc .hljs-bullet,
.markdown .hljs-bullet,
.asciidoc .hljs-link_url,
.markdown .hljs-link_url {
color: #05A5A8;
}
.hljs-label,
.ruby .hljs-string,
.hljs-decorator,
.hljs-filter .hljs-argument,
.hljs-localvars,
.hljs-array,
.hljs-attr_selector,
.hljs-important,
.hljs-pseudo,
.hljs-pi,
.haml .hljs-bullet,
.hljs-doctype,
.hljs-deletion,
.hljs-envvar,
.hljs-shebang,
.apache .hljs-sqbracket,
.nginx .hljs-built_in,
.tex .hljs-formula,
.erlang_repl .hljs-reserved,
.hljs-prompt,
.asciidoc .hljs-link_label,
.markdown .hljs-link_label,
.vhdl .hljs-attribute,
.clojure .hljs-attribute,
.asciidoc .hljs-attribute,
.lasso .hljs-attribute,
.coffeescript .hljs-property,
.hljs-phony {
color: #087599;
}
.hljs-keyword,
.hljs-id,
.hljs-title,
.hljs-built_in,
.css .hljs-tag,
.hljs-doctag,
.smalltalk .hljs-class,
.hljs-winutils,
.bash .hljs-variable,
.pf .hljs-variable,
.apache .hljs-tag,
.hljs-type,
.hljs-typename,
.tex .hljs-command,
.asciidoc .hljs-strong,
.markdown .hljs-strong,
.hljs-request,
.hljs-status,
.tp .hljs-data,
.tp .hljs-io {
font-weight: bold;
}
.asciidoc .hljs-emphasis,
.markdown .hljs-emphasis,
.tp .hljs-units {
font-style: italic;
}
.nginx .hljs-built_in {
font-weight: normal;
}
.coffeescript .javascript,
.javascript .xml,
.lasso .markup,
.tex .hljs-formula,
.xml .javascript,
.xml .vbscript,
.xml .css,
.xml .hljs-cdata {
opacity: 0.5;
}
/* -------------------------------------------------------
Sorting & Filtering with List.js (http://www.listjs.com/)
------------------------------------------------------- */
input.search {
border:solid 1px #ccc;
border-radius: 4px;
padding:7px;
margin-bottom:10px;
font-size: 12px;
}
input.search:focus {
outline:none;
border-color:#aaa;
}
th.sort::-moz-selection { background:transparent; }
th.sort::selection { background:transparent; }
th.sort { cursor:pointer; }
th.sort:after {
content:'';
display:inline-block;
width: 0;
height: 0;
position: relative;
top: -3px;
right: -6px;
border-width:0 4px 4px;
border-style:solid;
border-color:#404040 transparent;
visibility:hidden;
}
th.sort:hover:after { visibility:visible; }
th.sort.desc:after,
th.sort.asc:after,
th.sort.asc:hover:after {
visibility:visible;
opacity:0.6;
}
th.sort.desc:after {
border-bottom:none;
border-width:4px 4px 0;
}
================================================
FILE: bin/slather
================================================
#!/usr/bin/env ruby
require 'clamp'
require 'yaml'
require_relative '../lib/slather'
require_relative '../lib/slather/command/coverage_command'
require_relative '../lib/slather/command/setup_command'
require_relative '../lib/slather/command/version_command'
class MainCommand < Clamp::Command
self.default_subcommand = "coverage"
subcommand 'setup', 'Configures a .xcodeproj for test coverage generation', SetupCommand
subcommand 'coverage', 'Computes coverage for the supplied project', CoverageCommand
subcommand 'version', 'Prints slather version', VersionCommand
end
MainCommand.run
================================================
FILE: lib/cocoapods_plugin.rb
================================================
require_relative 'slather'
Pod::HooksManager.register('slather', :post_install) do |installer_context|
sandbox_root = installer_context.sandbox_root
sandbox = Pod::Sandbox.new(sandbox_root)
project = Xcodeproj::Project.open(sandbox.project_path)
project.slather_setup_for_coverage()
project.save()
end
================================================
FILE: lib/slather/command/coverage_command.rb
================================================
class CoverageCommand < Clamp::Command
parameter "[PROJECT]", "Path to the xcodeproj", :attribute_name => :xcodeproj_path
option ["--travis", "-t"], :flag, "Indicate that the builds are running on Travis CI"
option ["--travispro"], :flag, "Indicate that the builds are running on Travis Pro CI"
option ["--circleci"], :flag, "Indicate that the builds are running on CircleCI"
option ["--jenkins"], :flag, "Indicate that the builds are running on Jenkins"
option ["--buildkite"], :flag, "Indicate that the builds are running on Buildkite"
option ["--teamcity"], :flag, "Indicate that the builds are running on TeamCity"
option ["--github"], :flag, "Indicate that the builds are running on Github Actions"
option ["--coveralls", "-c"], :flag, "Post coverage results to coveralls"
option ["--simple-output", "-s"], :flag, "Output coverage results to the terminal"
option ["--gutter-json", "-g"], :flag, "Output coverage results as Gutter JSON format"
option ["--cobertura-xml", "-x"], :flag, "Output coverage results as Cobertura XML format"
option ["--sonarqube-xml", "-sq"], :flag, "Output coverage results as SonarQube XML format"
option ["--llvm-cov", "-r"], :flag, "Output coverage as llvm-cov format"
option ["--json"], :flag, "Output coverage results as simple JSON"
option ["--html"], :flag, "Output coverage results as static html pages"
option ["--show"], :flag, "Indicate that the static html pages will open automatically"
option ["--cdn-assets"], :flag, "Indicate that the static html pages will load assets from a CDN"
option ["--build-directory", "-b"], "BUILD_DIRECTORY", "The directory where gcno files will be written to. Defaults to derived data."
option ["--source-directory"], "SOURCE_DIRECTORY", "The directory where your source files are located."
option ["--output-directory"], "OUTPUT_DIRECTORY", "The directory where your Cobertura XML report will be written to."
option ["--ignore", "-i"], "IGNORE", "ignore files conforming to a path", :multivalued => true
option ["--verbose", "-v"], :flag, "Enable verbose mode"
option ["--input-format"], "INPUT_FORMAT", "Input format (gcov, profdata)"
option ["--scheme"], "SCHEME", "The scheme for which the coverage was generated"
option ["--configuration"], "CONFIGURATION", "The configuration for test that the project was set"
option ["--workspace"], "WORKSPACE", "The workspace that the project was built in"
option ["--binary-file"], "BINARY_FILE", "The binary file against which the coverage will be run", :multivalued => true
option ["--binary-basename"], "BINARY_BASENAME", "Basename of the file against which the coverage will be run", :multivalued => true
option ["--arch"], "ARCH", "Architecture to use from universal binaries"
option ["--source-files"], "SOURCE_FILES", "A Dir.glob compatible pattern used to limit the lookup to specific source files. Ignored in gcov mode.", :multivalued => true
option ["--decimals"], "DECIMALS", "The amount of decimals to use for % coverage reporting"
option ["--ymlfile"], "YMLFILE", "Relative path to a file used in place of '.slather.yml'"
def execute
puts "Slathering..."
setup_ymlfile # MUST be the first setup
setup_service_name
setup_ignore_list
setup_build_directory
setup_source_directory
setup_output_directory
setup_coverage_service
setup_verbose_mode
setup_input_format
setup_scheme
setup_configuration
setup_workspace
setup_binary_file
setup_binary_basename
setup_arch
setup_source_files
setup_decimals
project.configure
post
puts "Slathered"
end
def setup_ymlfile
Slather::Project.yml_filename = ymlfile if ymlfile
end
def setup_build_directory
project.build_directory = build_directory if build_directory
end
def setup_source_directory
project.source_directory = source_directory if source_directory
end
def setup_output_directory
project.output_directory = output_directory if output_directory
end
def setup_ignore_list
project.ignore_list = ignore_list if !ignore_list.empty?
end
def setup_service_name
if travis?
project.ci_service = :travis_ci
elsif travispro?
project.ci_service = :travis_pro
elsif circleci?
project.ci_service = :circleci
elsif jenkins?
project.ci_service = :jenkins
elsif buildkite?
project.ci_service = :buildkite
elsif teamcity?
project.ci_service = :teamcity
elsif github?
project.ci_service = :github
end
end
def post
project.post
end
def project
@project ||= begin
xcodeproj_path_to_open = xcodeproj_path || Slather::Project.yml["xcodeproj"]
if xcodeproj_path_to_open
project = Slather::Project.open(xcodeproj_path_to_open)
else
raise StandardError, "Must provide an xcodeproj either via the 'slather [SUBCOMMAND] [PROJECT].xcodeproj' command or through .slather.yml"
end
end
end
def setup_coverage_service
if coveralls?
project.coverage_service = :coveralls
elsif simple_output?
project.coverage_service = :terminal
elsif gutter_json?
project.coverage_service = :gutter_json
elsif cobertura_xml?
project.coverage_service = :cobertura_xml
elsif llvm_cov?
project.coverage_service = :llvm_cov
elsif html?
project.coverage_service = :html
project.show_html = show?
project.cdn_assets = cdn_assets?
elsif json?
project.coverage_service = :json
elsif sonarqube_xml?
project.coverage_service = :sonarqube_xml
end
end
def setup_verbose_mode
project.verbose_mode = verbose?
end
def setup_input_format
project.input_format = input_format
end
def setup_scheme
project.scheme = scheme
end
def setup_configuration
project.configuration = configuration
end
def setup_workspace
project.workspace = workspace
end
def setup_binary_file
project.binary_file = binary_file_list if !binary_file_list.empty?
end
def setup_binary_basename
project.binary_basename = binary_basename_list if !binary_basename_list.empty?
end
def setup_arch
project.arch = arch
end
def setup_source_files
project.source_files = source_files_list if !source_files_list.empty?
end
def setup_decimals
project.decimals = decimals if decimals
end
end
================================================
FILE: lib/slather/command/setup_command.rb
================================================
class SetupCommand < Clamp::Command
parameter "[PROJECT]", "Path to the .xcodeproj", :attribute_name => :xcodeproj_path
option ["--format"], "FORMAT", "Type of coverage to use (gcov, clang, auto)"
option ["--ymlfile"], "YMLFILE", "Relative path to a file used in place of '.slather.yml'"
def execute
setup_ymlfile
xcodeproj_path_to_open = xcodeproj_path || Slather::Project.yml["xcodeproj"]
unless xcodeproj_path_to_open
raise StandardError, "Must provide a .xcodeproj either via the 'slather [SUBCOMMAND] [PROJECT].xcodeproj' command or through .slather.yml"
end
project = Slather::Project.open(xcodeproj_path_to_open)
project.setup_for_coverage(format ? format.to_sym : :auto)
project.save
end
def setup_ymlfile
Slather::Project.yml_filename = ymlfile if ymlfile
end
end
================================================
FILE: lib/slather/command/version_command.rb
================================================
class VersionCommand < Clamp::Command
def execute
puts "slather #{Slather::VERSION}"
end
end
================================================
FILE: lib/slather/coverage_file.rb
================================================
require_relative 'coverage_info'
require_relative 'coveralls_coverage'
module Slather
class CoverageFile
include CoverageInfo
include CoverallsCoverage
attr_accessor :project, :gcno_file_pathname
def initialize(project, gcno_file_pathname)
self.project = project
self.gcno_file_pathname = Pathname(gcno_file_pathname)
end
def source_file_pathname
@source_file_pathname ||= begin
base_filename = gcno_file_pathname.basename.sub_ext("")
path = nil
if project.source_directory
path = Dir["#{project.source_directory}/**/#{base_filename}.{#{supported_file_extensions.join(",")}}"].first
path &&= Pathname(path)
else
pbx_file = project.files.detect { |pbx_file|
current_base_filename = pbx_file.real_path.basename
ext_name = File.extname(current_base_filename.to_s)[1..-1]
current_base_filename.sub_ext("") == base_filename && supported_file_extensions.include?(ext_name)
}
path = pbx_file && pbx_file.real_path
end
path
end
end
def source_file
File.new(source_file_pathname)
end
def source_data
source_file.read
end
def gcov_data
@gcov_data ||= begin
gcov_data = ""
Dir.chdir(project.project_dir) do
gcov_output = `gcov "#{source_file_pathname}" --object-directory "#{gcno_file_pathname.parent}" --branch-probabilities --branch-counts`
# Sometimes gcov makes gcov files for Cocoa Touch classes, like NSRange. Ignore and delete later.
gcov_files_created = gcov_output.scan(/creating '(.+\..+\.gcov)'/)
gcov_file_name = "./#{source_file_pathname.basename}.gcov"
if File.exist?(gcov_file_name)
gcov_data = File.new(gcov_file_name).read
else
gcov_data = ""
end
gcov_files_created.each { |file| FileUtils.rm_f(file) }
end
gcov_data
end
end
def all_lines
unless cleaned_gcov_data.empty?
first_line_start = cleaned_gcov_data =~ /^\s+(-|#+|[0-9+]):\s+1:/
cleaned_gcov_data[first_line_start..-1].split("\n").map
else
[]
end
end
def cleaned_gcov_data
data = gcov_data.encode('UTF-8', 'binary', invalid: :replace, undef: :replace, replace: '').gsub(/^function(.*) called [0-9]+ returned [0-9]+% blocks executed(.*)$\r?\n/, '')
data.gsub(/^branch(.*)$\r?\n/, '')
end
def raw_data
self.gcov_data
end
def line_coverage_data
unless cleaned_gcov_data.empty?
first_line_start = cleaned_gcov_data =~ /^\s+(-|#+|[0-9+]):\s+1:/
cleaned_gcov_data[first_line_start..-1].split("\n").map do |line|
coverage_for_line(line)
end
else
[]
end
end
def line_number_in_line(line)
line.split(':')[1].strip.to_i
end
def coverage_for_line(line)
line =~ /^(.+?):/
match = $1.strip
case match
when /[0-9]+/
match.to_i
when /#+/
0
when "-"
nil
end
end
def branch_coverage_data
@branch_coverage_data ||= begin
branch_coverage_data = Hash.new
gcov_data.scan(/(^(\s+(-|#+|[0-9]+):\s+[1-9]+:(.*)$\r?\n)(^branch\s+[0-9]+\s+[a-zA-Z0-9]+\s+[a-zA-Z0-9]+$\r?\n)+)+/) do |data|
lines = data[0].split("\n")
line_number = lines[0].split(':')[1].strip.to_i
branch_coverage_data[line_number] = lines[1..-1].map do |line|
if line.split(' ')[2].strip == "never"
0
else
line.split(' ')[3].strip.to_i
end
end
end
branch_coverage_data
end
end
def source_file_basename
File.basename(source_file_pathname, '.m')
end
def line_number_separator
":"
end
def supported_file_extensions
["cpp", "mm", "m"]
end
private :supported_file_extensions
end
end
================================================
FILE: lib/slather/coverage_info.rb
================================================
module Slather
module CoverageInfo
def num_lines_tested
line_coverage_data.compact.select { |cd| cd > 0 }.count
end
def num_lines_testable
line_coverage_data.compact.count
end
def rate_lines_tested
if num_lines_testable > 0
(num_lines_tested / num_lines_testable.to_f)
else
0
end
end
def percentage_lines_tested
if num_lines_testable == 0
100
else
rate_lines_tested * 100
end
end
def branch_coverage_data_for_statement_on_line(line_number)
branch_coverage_data[line_number] || []
end
def num_branches_for_statement_on_line(line_number)
branch_coverage_data_for_statement_on_line(line_number).length
end
def num_branch_hits_for_statement_on_line(line_number)
branch_coverage_data_for_statement_on_line(line_number).count { |hit_count| hit_count > 0 }
end
def rate_branch_coverage_for_statement_on_line(line_number)
branch_data = branch_coverage_data_for_statement_on_line(line_number)
if branch_data.empty?
0.0
else
(num_branch_hits_for_statement_on_line(line_number) / branch_data.length.to_f)
end
end
def percentage_branch_coverage_for_statement_on_line(line_number)
rate_branch_coverage_for_statement_on_line(line_number) * 100
end
def num_branches_testable
branch_coverage_data.keys.reduce(0) do |sum, line_number|
sum += num_branches_for_statement_on_line(line_number)
end
end
def num_branches_tested
branch_coverage_data.keys.reduce(0) do |sum, line_number|
sum += num_branch_hits_for_statement_on_line(line_number)
end
end
def rate_branches_tested
if (num_branches_testable > 0)
(num_branches_tested / num_branches_testable.to_f)
else
0.0
end
end
def source_file_pathname_relative_to_repo_root
source_file_pathname.realpath.relative_path_from(Pathname("./").realpath)
end
def ignored?
project.ignore_list.any? do |ignore|
File.fnmatch(ignore, source_file_pathname_relative_to_repo_root)
end
end
def include_file?
rv = true # default true return value to fix https://github.com/SlatherOrg/slather/issues/561
project.source_files.any? do |include|
rv = File.fnmatch(include, source_file_pathname_relative_to_repo_root)
end
rv
end
end
end
================================================
FILE: lib/slather/coverage_service/cobertura_xml_output.rb
================================================
require 'nokogiri'
require 'date'
module Slather
module CoverageService
module CoberturaXmlOutput
def coverage_file_class
if input_format == "profdata"
Slather::ProfdataCoverageFile
else
Slather::CoverageFile
end
end
private :coverage_file_class
def post
cobertura_xml_report = create_xml_report(coverage_files)
store_report(cobertura_xml_report)
end
def store_report(report)
output_file = 'cobertura.xml'
if output_directory
FileUtils.mkdir_p(output_directory)
output_file = File.join(output_directory, output_file)
end
File.write(output_file, report.to_s)
end
def grouped_coverage_files(coverage_files)
groups = Hash.new
coverage_files.each do |coverage_file|
next if coverage_file == nil
path = File.dirname(coverage_file.source_file_pathname_relative_to_repo_root)
if groups[path] == nil
groups[path] = Array.new
end
groups[path].push(coverage_file)
end
groups
end
def create_xml_report(coverage_files)
total_project_lines = 0
total_project_lines_tested = 0
total_project_line_rate = '%.16f' % 1.0
total_project_branches = 0
total_project_branches_tested = 0
total_project_branch_rate = '%.16f' % 1.0
create_empty_xml_report
coverage_node = @doc.root
source_node = @doc.at_css "source"
source_node.content = Pathname.pwd.to_s
packages_node = @doc.at_css "packages"
# group files by path
grouped_coverage_files(coverage_files).each do |path , package_coverage_files|
package_node = Nokogiri::XML::Node.new "package", @doc
package_node.parent = packages_node
classes_node = Nokogiri::XML::Node.new "classes", @doc
classes_node.parent = package_node
package_node['name'] = path.gsub(/\//, '.')
total_package_lines = 0
total_package_lines_tested = 0
total_package_lines_rate = '%.16f' % 1.0
total_package_branches = 0
total_package_branches_tested = 0
total_package_branch_rate = '%.16f' % 1.0
package_coverage_files.each do |package_coverage_file|
class_node = create_class_node(package_coverage_file)
class_node.parent = classes_node
total_package_lines += package_coverage_file.num_lines_testable
total_package_lines_tested += package_coverage_file.num_lines_tested
total_package_branches += package_coverage_file.num_branches_testable
total_package_branches_tested += package_coverage_file.num_branches_tested
end
if (total_package_lines > 0)
total_package_line_rate = '%.16f' % (total_package_lines_tested / total_package_lines.to_f)
end
if (total_package_branches > 0)
total_package_branch_rate = '%.16f' % (total_package_branches_tested / total_package_branches.to_f)
end
package_node['line-rate'] = total_package_line_rate
package_node['branch-rate'] = total_package_branch_rate
package_node['complexity'] = '0.0'
total_project_lines += total_package_lines
total_project_lines_tested += total_package_lines_tested
total_project_branches += total_package_branches
total_project_branches_tested += total_package_branches_tested
end
if (total_project_lines > 0)
total_project_line_rate = '%.16f' % (total_project_lines_tested / total_project_lines.to_f)
end
if (total_project_branches > 0)
total_project_branch_rate = '%.16f' % (total_project_branches_tested / total_project_branches.to_f)
end
coverage_node['line-rate'] = total_project_line_rate
coverage_node['branch-rate'] = total_project_branch_rate
coverage_node['lines-covered'] = total_project_lines_tested
coverage_node['lines-valid'] = total_project_lines
coverage_node['branches-covered'] = total_project_branches_tested
coverage_node['branches-valid'] = total_project_branches
coverage_node['complexity'] = "0.0"
coverage_node['timestamp'] = DateTime.now.strftime('%s')
coverage_node['version'] = "Slather #{Slather::VERSION}"
@doc.to_xml
end
def create_class_node(coverage_file)
filename = coverage_file.source_file_basename
filepath = coverage_file.source_file_pathname_relative_to_repo_root.to_s
class_node = Nokogiri::XML::Node.new "class", @doc
class_node['name'] = filename
class_node['filename'] = filepath
class_node['line-rate'] = '%.16f' % [(coverage_file.num_lines_testable > 0) ? coverage_file.rate_lines_tested : 1.0]
class_node['branch-rate'] = '%.16f' % [(coverage_file.num_branches_testable > 0) ? coverage_file.rate_branches_tested : 1.0]
class_node['complexity'] = '0.0'
methods_node = Nokogiri::XML::Node.new "methods", @doc
methods_node.parent = class_node
lines_node = Nokogiri::XML::Node.new "lines", @doc
lines_node.parent = class_node
coverage_file.all_lines.each do |line|
if coverage_file.coverage_for_line(line)
line_node = create_line_node(line, coverage_file)
line_node.parent = lines_node
end
end
class_node
end
def create_line_node(line, coverage_file)
line_number = coverage_file.line_number_in_line(line)
line_node = Nokogiri::XML::Node.new "line", @doc
line_node['number'] = line_number
line_node['branch'] = "false"
line_node['hits'] = coverage_file.coverage_for_line(line)
unless coverage_file.branch_coverage_data_for_statement_on_line(line_number).empty?
line_node['branch'] = "true"
conditions_node = Nokogiri::XML::Node.new "conditions", @doc
conditions_node.parent = line_node
condition_node = Nokogiri::XML::Node.new "condition", @doc
condition_node.parent = conditions_node
condition_node['number'] = "0"
condition_node['type'] = "jump"
branches_testable = coverage_file.num_branches_for_statement_on_line(line_number)
branch_hits = coverage_file.num_branch_hits_for_statement_on_line(line_number)
condition_coverage = coverage_file.percentage_branch_coverage_for_statement_on_line(line_number)
condition_node['coverage'] = "#{condition_coverage.to_i}%"
line_node['condition-coverage'] = "#{condition_coverage.to_i}% (#{branch_hits}/#{branches_testable})"
end
line_node
end
def create_empty_xml_report
builder = Nokogiri::XML::Builder.new do |xml|
xml.doc.create_internal_subset(
'coverage',
nil,
"https://raw.githubusercontent.com/cobertura/cobertura/master/cobertura/src/site/htdocs/xml/coverage-04.dtd"
)
xml.coverage do
xml.sources do
xml.source
end
xml.packages
end
end
@doc = builder.doc
end
end
end
end
================================================
FILE: lib/slather/coverage_service/coveralls.rb
================================================
module Slather
module CoverageService
module Coveralls
def coverage_file_class
if input_format == "profdata"
Slather::ProfdataCoverageFile
else
Slather::CoverageFile
end
end
private :coverage_file_class
def travis_job_id
ENV['TRAVIS_JOB_ID']
end
private :travis_job_id
def circleci_job_id
ENV['CIRCLE_BUILD_NUM']
end
private :circleci_job_id
def circleci_pull_request
ENV['CIRCLE_PR_NUMBER'] || ENV['CI_PULL_REQUEST'] || ""
end
private :circleci_pull_request
def teamcity_job_id
ENV['TC_BUILD_NUMBER']
end
private :teamcity_job_id
def jenkins_job_id
ENV['BUILD_ID']
end
private :jenkins_job_id
def github_job_id
ENV['GITHUB_RUN_ID']
end
private :github_job_id
def bitrise_job_id
ENV['BITRISE_BUILD_NUMBER']
end
private :bitrise_job_id
def bitrise_pull_request
ENV['BITRISE_PULL_REQUEST']
end
private :bitrise_pull_request
def github_pull_request
ENV['CI_PULL_REQUEST'] || ""
end
private :github_pull_request
def github_repo_name
ENV['GITHUB_REPOSITORY'] || ""
end
private :github_repo_name
def jenkins_branch_name
branch_name = ENV['GIT_BRANCH'] || ENV['BRANCH_NAME']
if branch_name.include? 'origin/'
branch_name[7...branch_name.length]
else
branch_name
end
end
private :jenkins_branch_name
def teamcity_branch_name
ENV['GIT_BRANCH'] || `git ls-remote --heads origin | grep $(git rev-parse HEAD) | cut -d / -f 3-`.chomp
end
private :teamcity_branch_name
def github_branch_name
ENV['GIT_BRANCH'] || `git ls-remote --heads origin | grep $(git rev-parse HEAD) | cut -d / -f 3-`.chomp
end
private :github_branch_name
def bitrise_branch_name
ENV['BITRISE_GIT_BRANCH'] || `git ls-remote --heads origin | grep $(git rev-parse HEAD) | cut -d / -f 3-`.chomp
end
private :bitrise_branch_name
def buildkite_job_id
ENV['BUILDKITE_BUILD_NUMBER']
end
private :buildkite_job_id
def buildkite_pull_request
ENV['BUILDKITE_PULL_REQUEST']
end
private :buildkite_pull_request
def jenkins_git_info
{
head: {
id: ENV['sha1'],
author_name: ENV['ghprbActualCommitAuthor'],
message: ENV['ghprbPullTitle']
},
branch: jenkins_branch_name
}
end
private :jenkins_git_info
def teamcity_git_info
{
head: {
:id => (`git log --format=%H -n 1 HEAD`.chomp || ""),
:author_name => (`git log --format=%an -n 1 HEAD`.chomp || ""),
:author_email => (`git log --format=%ae -n 1 HEAD`.chomp || ""),
:message => (`git log --format=%s -n 1 HEAD`.chomp || "")
},
:branch => teamcity_branch_name
}
end
private :teamcity_git_info
def circleci_build_url
"https://circleci.com/gh/" + ENV['CIRCLE_PROJECT_USERNAME'] || "" + "/" + ENV['CIRCLE_PROJECT_REPONAME'] || "" + "/" + ENV['CIRCLE_BUILD_NUM'] || ""
end
private :circleci_build_url
def circleci_git_info
{
:head => {
:id => (ENV['CIRCLE_SHA1'] || ""),
:author_name => (ENV['CIRCLE_PR_USERNAME'] || ENV['CIRCLE_USERNAME'] || ""),
:message => (`git log --format=%s -n 1 HEAD`.chomp || "")
},
:branch => (ENV['CIRCLE_BRANCH'] || "")
}
end
private :circleci_git_info
def buildkite_git_info
{
:head => {
:id => ENV['BUILDKITE_COMMIT'],
:author_name => (`git log --format=%an -n 1 HEAD`.chomp || ""),
:author_email => (`git log --format=%ae -n 1 HEAD`.chomp || ""),
:message => (`git log --format=%s -n 1 HEAD`.chomp || "")
},
:branch => ENV['BUILDKITE_BRANCH']
}
end
def buildkite_build_url
"https://buildkite.com/" + ENV['BUILDKITE_PROJECT_SLUG'] + "/builds/" + ENV['BUILDKITE_BUILD_NUMBER'] + "#"
end
def github_git_info
{
:head => {
:id => ENV['GITHUB_SHA'],
:author_name => ENV['GITHUB_ACTOR'],
:message => (`git log --format=%s -n 1 HEAD`.chomp || "")
},
:branch => github_branch_name
}
end
private :github_git_info
def bitrise_git_info
{
:head => {
:id => ENV['BITRISE_GIT_COMMIT'],
:committer_name => (ENV['GIT_CLONE_COMMIT_AUTHOR_NAME'] || `git log --format=%an -n 1 HEAD`.chomp || ""),
:committer_email => (ENV['GIT_CLONE_COMMIT_AUTHOR_EMAIL'] || `git log --format=%ae -n 1 HEAD`.chomp || ""),
:message => (ENV['BITRISE_GIT_MESSAGE'] || `git log --format=%s -n 1 HEAD`.chomp || "")
},
:branch => bitrise_branch_name
}
end
private :bitrise_git_info
def github_build_url
"https://github.com/" + ENV['GITHUB_REPOSITORY'] + "/actions/runs/" + ENV['GITHUB_RUN_ID']
end
private :github_build_url
def is_parallel
ENV['IS_PARALLEL'] != nil
end
private :is_parallel
def github_job_name
ENV['GITHUB_JOB']
end
private :github_job_name
def coveralls_coverage_data
if ci_service == :travis_ci || ci_service == :travis_pro
if travis_job_id
if ci_service == :travis_ci
if coverage_access_token.to_s.strip.length > 0
raise StandardError, "Access token is set. Uploading coverage data for public repositories doesn't require an access token."
end
{
:service_job_id => travis_job_id,
:service_name => "travis-ci",
:source_files => coverage_files.map(&:as_json)
}.to_json
elsif ci_service == :travis_pro
if coverage_access_token.to_s.strip.length == 0
raise StandardError, "Access token is not set. Uploading coverage data for private repositories requires an access token."
end
{
:service_job_id => travis_job_id,
:service_name => "travis-pro",
:repo_token => coverage_access_token,
:source_files => coverage_files.map(&:as_json)
}.to_json
end
else
raise StandardError, "Environment variable `TRAVIS_JOB_ID` not set. Is this running on a travis build?"
end
elsif ci_service == :circleci
if circleci_job_id
coveralls_hash = {
:service_job_id => circleci_job_id,
:service_name => "circleci",
:repo_token => coverage_access_token,
:source_files => coverage_files.map(&:as_json),
:git => circleci_git_info,
:service_build_url => circleci_build_url
}
if circleci_pull_request != nil && circleci_pull_request.length > 0
coveralls_hash[:service_pull_request] = circleci_pull_request.split("/").last
end
coveralls_hash.to_json
else
raise StandardError, "Environment variable `CIRCLE_BUILD_NUM` not set. Is this running on a circleci build?"
end
elsif ci_service == :jenkins
if jenkins_job_id
{
service_job_id: jenkins_job_id,
service_name: "jenkins",
repo_token: coverage_access_token,
source_files: coverage_files.map(&:as_json),
git: jenkins_git_info
}.to_json
else
raise StandardError, "Environment variable `BUILD_ID` not set. Is this running on a jenkins build?"
end
elsif ci_service == :buildkite
if buildkite_job_id
{
:service_job_id => buildkite_job_id,
:service_name => "buildkite",
:repo_token => coverage_access_token,
:source_files => coverage_files.map(&:as_json),
:git => buildkite_git_info,
:service_build_url => buildkite_build_url,
:service_pull_request => buildkite_pull_request
}.to_json
else
raise StandardError, "Environment variable `BUILDKITE_BUILD_NUMBER` not set. Is this running on a buildkite build?"
end
elsif ci_service == :teamcity
if teamcity_job_id
{
:service_job_id => teamcity_job_id,
:service_name => "teamcity",
:repo_token => coverage_access_token,
:source_files => coverage_files.map(&:as_json),
:git => teamcity_git_info
}.to_json
else
raise StandardError, "Environment variable `TC_BUILD_NUMBER` not set. Is this running on a teamcity build?"
end
elsif ci_service == :github
if coverage_access_token.to_s.strip.length == 0
raise StandardError, "Access token is not set. Uploading coverage data for private repositories requires an access token."
end
if github_job_id
{
:service_job_id => github_job_id,
:service_name => "github",
:repo_token => coverage_access_token,
:repo_name => github_repo_name,
:source_files => coverage_files.map(&:as_json),
:service_build_url => github_build_url,
:service_pull_request => github_pull_request,
:git => github_git_info,
:parallel => is_parallel,
:flag_name => github_job_name
}.to_json
else
raise StandardError, "Environment variable `GITHUB_RUN_ID` not set. Is this running on github build?"
end
elsif ci_service == :bitrise
{
:service_job_id => bitrise_job_id,
:service_name => 'bitrise',
:repo_token => coverage_access_token,
:source_files => coverage_files.map(&:as_json),
:service_pull_request => bitrise_pull_request,
:service_branch => bitrise_branch_name,
:git => bitrise_git_info
}.to_json
else
{
:service_job_id => ENV['CI_BUILD_NUMBER'],
:service_name => ENV['CI_NAME'] || ci_service,
:repo_token => coverage_access_token,
:source_files => coverage_files.map(&:as_json),
:service_build_url => ENV['CI_BUILD_URL'],
:service_pull_request => ENV['CI_PULL_REQUEST'],
:service_branch => ENV['CI_BRANCH'],
:git => {
:head => {
:id => ENV['CI_COMMIT'],
:committer_name => (`git log --format=%an -n 1 HEAD`.chomp || ""),
:committer_email => (`git log --format=%ae -n 1 HEAD`.chomp || ""),
:message => (`git log --format=%s -n 1 HEAD`.chomp || "")
},
:branch => ENV['CI_BRANCH']
}
}.to_json
end
end
private :coveralls_coverage_data
def post
f = File.open('coveralls_json_file', 'w+')
begin
f.write(coveralls_coverage_data)
f.close
curl_result = `curl -s --form json_file=@#{f.path} #{coveralls_api_jobs_path}`
if curl_result.is_a? String
curl_result_json = JSON.parse(curl_result)
if curl_result_json["error"]
error_message = curl_result_json["message"]
raise StandardError, "Error while uploading coverage data to Coveralls. CI Service: #{ci_service} Message: #{error_message}"
end
end
rescue StandardError => e
FileUtils.rm(f)
raise e
end
FileUtils.rm(f)
end
def coveralls_api_jobs_path
"https://coveralls.io/api/v1/jobs"
end
private :coveralls_api_jobs_path
end
end
end
================================================
FILE: lib/slather/coverage_service/gutter_json_output.rb
================================================
module Slather
module CoverageService
module GutterJsonOutput
def coverage_file_class
if input_format == "profdata"
Slather::ProfdataCoverageFile
else
Slather::CoverageFile
end
end
private :coverage_file_class
def post
output = { 'meta' => { 'timestamp' => DateTime.now.strftime('%Y-%m-%d %H:%M:%S.%6N') } }
symbols = {}
coverage_files.each do |coverage_file|
next unless coverage_file.raw_data
filename = coverage_file.source_file_pathname.to_s
filename = filename.sub(Pathname.pwd.to_s, '').reverse.chomp("/").reverse
coverage_file.all_lines.each do |line|
line_number = coverage_file.line_number_in_line(line)
next unless line_number > 0
coverage = coverage_file.coverage_for_line(line)
short_text = coverage != nil ? coverage.to_s : "-"
symbol = { 'line' => line_number,
'long_text' => '',
'short_text' => short_text }
if coverage != nil
symbol['background_color'] = coverage.to_i > 0 ? '0x35CC4B' : '0xFC635E'
end
if symbols.has_key?(filename)
symbols[filename] << symbol
else
symbols[filename] = [ symbol ]
end
end
end
output['symbols_by_file'] = symbols
File.open('.gutter.json', 'w') { |file| file.write(output.to_json) }
end
end
end
end
================================================
FILE: lib/slather/coverage_service/hardcover.rb
================================================
module Slather
module CoverageService
module Hardcover
def coverage_file_class
if input_format == "profdata"
Slather::ProfdataCoverageFile
else
Slather::CoverageFile
end
end
private :coverage_file_class
def jenkins_job_id
"#{ENV['JOB_NAME']}/#{ENV['BUILD_NUMBER']}"
end
private :jenkins_job_id
def hardcover_coverage_data
if ci_service == :jenkins_ci
if jenkins_job_id
{
:service_job_id => jenkins_job_id,
:service_name => "jenkins-ci",
:repo_token => Project.yml["hardcover_repo_token"],
:source_files => coverage_files.map(&:as_json)
}.to_json
else
raise StandardError, "Environment variables `BUILD_NUMBER` and `JOB_NAME` are not set. Is this running on a Jenkins build?"
end
else
raise StandardError, "No support for ci named #{ci_service}"
end
end
private :hardcover_coverage_data
def post
f = File.open('hardcover_json_file', 'w+')
begin
f.write(hardcover_coverage_data)
f.close
`curl --form json_file=@#{f.path} #{hardcover_api_jobs_path}`
rescue StandardError => e
FileUtils.rm(f)
raise e
end
FileUtils.rm(f)
end
def hardcover_api_jobs_path
"#{hardcover_base_url}/v1/jobs"
end
private :hardcover_api_jobs_path
def hardcover_base_url
url = Project.yml["hardcover_base_url"]
unless url
raise "No `hardcover_base_url` configured. Please add it to your `.slather.yml`"
end
url
end
private :hardcover_base_url
end
end
end
================================================
FILE: lib/slather/coverage_service/html_output.rb
================================================
require 'nokogiri'
require "cgi"
module Slather
module CoverageService
module HtmlOutput
attr_reader :docs
def coverage_file_class
if input_format == "profdata"
Slather::ProfdataCoverageFile
else
Slather::CoverageFile
end
end
private :coverage_file_class
def directory_path
is_path_valid = !output_directory.nil? && !output_directory.strip.eql?("")
is_path_valid ? File.expand_path(output_directory) : "html"
end
private :directory_path
def post
create_html_reports(coverage_files)
generate_reports(@docs)
index_html_path = File.join(directory_path, "index.html")
if show_html
open_coverage index_html_path
else
print_path_coverage index_html_path
end
end
def print_path_coverage(index_html)
path = File.expand_path index_html
puts "\nTo open the html reports, use \n\nopen '#{path}'\n\nor use '--show' flag to open it automatically.\n\n"
end
def open_coverage(index_html)
path = File.expand_path index_html
`open '#{path}'` if File.exist?(path)
end
def create_html_reports(coverage_files)
create_index_html(coverage_files)
create_htmls_from_files(coverage_files)
end
def generate_reports(reports)
FileUtils.rm_rf(directory_path) if Dir.exist?(directory_path)
FileUtils.mkdir_p(directory_path)
FileUtils.cp(File.join(gem_root_path, "docs/logo.jpg"), directory_path)
FileUtils.cp(File.join(gem_root_path, "assets/slather.css"), directory_path)
FileUtils.cp(File.join(gem_root_path, "assets/highlight.pack.js"), directory_path)
FileUtils.cp(File.join(gem_root_path, "assets/list.min.js"), directory_path)
reports.each do |name, doc|
html_file = File.join(directory_path, "#{name}.html")
File.write(html_file, doc.to_html)
end
end
def create_index_html(coverage_files)
project_name = File.basename(self.xcodeproj)
template = generate_html_template(project_name, true, false)
total_relevant_lines = 0
total_tested_lines = 0
total_relevant_branches = 0
total_branches_tested = 0
coverage_files.each { |coverage_file|
total_tested_lines += coverage_file.num_lines_tested
total_relevant_lines += coverage_file.num_lines_testable
total_relevant_branches += coverage_file.num_branches_testable
total_branches_tested += coverage_file.num_branches_tested
}
builder = Nokogiri::HTML::Builder.with(template.at('#reports')) { |cov|
cov.h2 "Files for \"#{project_name}\""
cov.h4 {
percentage = (total_tested_lines / total_relevant_lines.to_f) * 100.0
cov.span "Total Coverage : "
cov.span decimal_f(percentage) + '%', :class => class_for_coverage_percentage(percentage), :id => "total_coverage"
cov.span " ("
cov.span total_tested_lines, :id => "total_tested_lines"
cov.span " of "
cov.span total_relevant_lines, :id => "total_relevant_lines"
cov.span " lines)"
}
cov.h4 {
percentage = (total_branches_tested / total_relevant_branches.to_f) * 100.0
cov.span "Total Branch Coverage : "
cov.span decimal_f(percentage) + '%', :class => class_for_coverage_percentage(percentage), :id => "total_coverage"
cov.span " ("
cov.span total_branches_tested, :id => "total_branches_tested"
cov.span " of "
cov.span total_relevant_branches, :id => "total_relevant_branches"
cov.span " lines)"
}
cov.input(:class => "search", :placeholder => "Search")
cov.table(:class => "coverage_list", :cellspacing => 0, :cellpadding => 0) {
cov.thead {
cov.tr {
cov.th "%", :class => "col_num sort", "data-sort" => "data_percentage"
cov.th "File", :class => "sort", "data-sort" => "data_filename"
cov.th "Lines", :class => "col_percent sort", "data-sort" => "data_lines"
cov.th "Relevant", :class => "col_percent sort", "data-sort" => "data_relevant"
cov.th "Covered", :class => "col_percent sort", "data-sort" => "data_covered"
cov.th "Missed", :class => "col_percent sort", "data-sort" => "data_missed"
}
}
cov.tbody(:class => "list") {
coverage_files.each { |coverage_file|
filename = File.basename(coverage_file.source_file_pathname_relative_to_repo_root)
filename_link = CGI.escape(filename) + ".html"
cov.tr {
percentage = coverage_file.percentage_lines_tested
cov.td { cov.span decimal_f(percentage), :class => "percentage #{class_for_coverage_percentage(percentage)} data_percentage" }
cov.td(:class => "data_filename") {
cov.a filename, :href => filename_link
}
cov.td "#{coverage_file.line_coverage_data.count}", :class => "data_lines"
cov.td "#{coverage_file.num_lines_testable}", :class => "data_relevant"
cov.td "#{coverage_file.num_lines_tested}", :class => "data_covered"
cov.td "#{(coverage_file.num_lines_testable - coverage_file.num_lines_tested)}", :class => "data_missed"
}
}
}
}
}
@docs = Hash.new
@docs[:index] = builder.doc
end
def create_htmls_from_files(coverage_files)
coverage_files.map { |file| create_html_from_file file }
end
def create_html_from_file(coverage_file)
filepath = coverage_file.source_file_pathname_relative_to_repo_root
filename = File.basename(filepath)
percentage = coverage_file.percentage_lines_tested
branch_percentage = coverage_file.rate_branches_tested * 100
cleaned_gcov_lines = coverage_file.cleaned_gcov_data.split("\n")
is_file_empty = (cleaned_gcov_lines.count <= 0)
template = generate_html_template(filename, false, is_file_empty)
builder = Nokogiri::HTML::Builder.with(template.at('#reports')) { |cov|
cov.h2(:class => "cov_title") {
cov.span("Coverage for \"#{filename}\"" + (!is_file_empty ? " : " : ""))
cov.span("Lines: ") unless is_file_empty
cov.span("#{decimal_f(percentage)}%", :class => class_for_coverage_percentage(percentage)) unless is_file_empty
cov.span(" Branches: ") unless is_file_empty
cov.span("#{decimal_f(branch_percentage)}%", :class => class_for_coverage_percentage(branch_percentage)) unless is_file_empty
}
cov.h4("(#{coverage_file.num_lines_tested} of #{coverage_file.num_lines_testable} relevant lines covered)", :class => "cov_subtitle")
cov.h4(filepath, :class => "cov_filepath")
if is_file_empty
cov.p "¯\\_(ツ)_/¯"
next
end
line_number_separator = coverage_file.line_number_separator
cov.table(:class => "source_code") {
cleaned_gcov_lines.each do |line|
line_number = coverage_file.line_number_in_line(line)
missed_regions = coverage_file.branch_region_data[line_number]
hits = coverage_file.coverage_for_line(line)
next unless line_number > 0
line_source = line.split(line_number_separator, 3)[2]
line_data = [line_number, line_source, hits_for_coverage_line(coverage_file, line)]
classes = ["num", "src", "coverage"]
cov.tr(:class => class_for_coverage_line(coverage_file,line)) {
line_data.each_with_index { |line, idx|
if idx != 1
cov.td(line, :class => classes[idx])
else
cov.td(:class => classes[idx]) {
cov.pre {
# If the line has coverage and missed regions, split up
# the line to show regions that weren't covered
if missed_regions != nil && hits != nil && hits > 0
regions = missed_regions.map do |region|
region_start, region_length = region
if region_length != nil
line[region_start, region_length]
else
line[region_start, line.length - region_start]
end
end
current_line = line
regions.each do |region|
covered, remainder = current_line.split(region, 2)
cov.code(covered, :class => "objc")
cov.code(region, :class => "objc missed")
current_line = remainder
end
cov.code(current_line, :class => "objc")
else
cov.code(line, :class => "objc")
end
}
}
end
}
}
end
}
}
@docs[filename] = builder.doc
end
def generate_html_template(title, is_index, is_file_empty)
if cdn_assets
logo_path = "https://cdn.jsdelivr.net/gh/SlatherOrg/slather/docs/logo.jpg"
css_path = "https://cdn.jsdelivr.net/gh/SlatherOrg/slather/assets/slather.css"
highlight_js_path = "https://cdn.jsdelivr.net/gh/SlatherOrg/slather/assets/highlight.pack.js"
list_js_path = "https://cdn.jsdelivr.net/gh/SlatherOrg/slather/assets/list.min.js"
else
logo_path = "logo.jpg"
css_path = "slather.css"
highlight_js_path = "highlight.pack.js"
list_js_path = "list.min.js"
end
builder = Nokogiri::HTML::Builder.new do |doc|
doc.html {
doc.head {
doc.title "#{title} - Slather"
doc.link :href => css_path, :media => "all", :rel => "stylesheet"
}
doc.body {
doc.header {
doc.div(:class => "row") {
doc.a(:href => "index.html") { doc.img(:src => logo_path, :alt => "Slather logo") }
}
}
doc.div(:class => "row") { doc.div(:id => "reports") }
doc.footer {
doc.div(:class => "row") {
doc.p { doc.a("Fork me on Github", :href => "https://github.com/SlatherOrg/slather") }
doc.p("© #{Date.today.year} Slather")
}
}
if is_index
doc.script :src => list_js_path
doc.script "var reports = new List('reports', { valueNames: [ 'data_percentage', 'data_filename', 'data_lines', 'data_relevant', 'data_covered', 'data_missed' ]});"
else
unless is_file_empty
doc.script :src => highlight_js_path
doc.script "hljs.initHighlightingOnLoad();"
end
end
}
}
end
builder.doc
end
def gem_root_path
File.expand_path File.join(File.dirname(__dir__), "../..")
end
def class_for_coverage_line(coverage_file, coverage_line)
hits = coverage_file.coverage_for_line(coverage_line)
case
when hits == nil then "never"
when hits > 0 then "covered"
else "missed"
end
end
def hits_for_coverage_line(coverage_file, coverage_line)
hits = coverage_file.coverage_for_line(coverage_line)
case
when hits == nil then ""
when hits > 0 then "#{hits}x"
else "!"
end
end
def class_for_coverage_percentage(percentage)
case
when percentage > 85 then "cov_high"
when percentage > 70 then "cov_medium"
else "cov_low"
end
end
end
end
end
================================================
FILE: lib/slather/coverage_service/json_output.rb
================================================
require 'nokogiri'
require 'date'
module Slather
module CoverageService
module JsonOutput
def coverage_file_class
if input_format == "profdata"
Slather::ProfdataCoverageFile
else
Slather::CoverageFile
end
end
private :coverage_file_class
def post
report = coverage_files.map do |file|
{
file: file.source_file_pathname_relative_to_repo_root,
coverage: file.line_coverage_data
}
end.to_json
store_report(report)
end
def store_report(report)
output_file = 'report.json'
if output_directory
FileUtils.mkdir_p(output_directory)
output_file = File.join(output_directory, output_file)
end
File.write(output_file, report.to_s)
end
end
end
end
================================================
FILE: lib/slather/coverage_service/llvm_cov_output.rb
================================================
require 'nokogiri'
require 'date'
module Slather
module CoverageService
module LlvmCovOutput
def coverage_file_class
if input_format == "profdata"
Slather::ProfdataCoverageFile
else
raise StandardError, "Only profdata input format supported by llvm-cov show."
end
end
private :coverage_file_class
def post
report = coverage_files.map do |file|
["#{file.source_file_pathname.realpath}:", file.source_data, ""]
end.flatten.join("\n")
store_report(report)
end
def store_report(report)
output_file = 'report.llcov'
if output_directory
FileUtils.mkdir_p(output_directory)
output_file = File.join(output_directory, output_file)
end
File.write(output_file, report.to_s)
end
end
end
end
================================================
FILE: lib/slather/coverage_service/simple_output.rb
================================================
module Slather
module CoverageService
module SimpleOutput
def coverage_file_class
if input_format == "profdata"
Slather::ProfdataCoverageFile
else
Slather::CoverageFile
end
end
private :coverage_file_class
def post
total_project_lines = 0
total_project_lines_tested = 0
coverage_files.each do |coverage_file|
# ignore lines that don't count towards coverage (comments, whitespace, etc). These are nil in the array.
lines_tested = coverage_file.num_lines_tested
total_lines = coverage_file.num_lines_testable
percentage = decimal_f([coverage_file.percentage_lines_tested])
total_project_lines_tested += lines_tested
total_project_lines += total_lines
puts "#{coverage_file.source_file_pathname_relative_to_repo_root}: #{lines_tested} of #{total_lines} lines (#{percentage}%)"
end
# check if there needs to be custom reporting based on the ci service
if ci_service == :teamcity
# TeamCity Build Statistic Reporting
#
# Reporting format ##teamcity[buildStatisticValue key='<valueTypeKey>' value='<value>']
# key='CodeCoverageAbsLCovered' is total number of lines covered
# key='CodeCoverageAbsLTotal' is total number of lines
#
# Sources:
# - https://confluence.jetbrains.com/display/TCDL/Build+Script+Interaction+with+TeamCity#BuildScriptInteractionwithTeamCity-ReportingBuildStatistics
# - https://confluence.jetbrains.com/display/TCDL/Custom+Chart#CustomChart-listOfDefaultStatisticValues
puts "##teamcity[buildStatisticValue key='CodeCoverageAbsLCovered' value='%i']" % total_project_lines_tested
puts "##teamcity[buildStatisticValue key='CodeCoverageAbsLTotal' value='%i']" % total_project_lines
end
total_percentage = decimal_f([(total_project_lines_tested / total_project_lines.to_f) * 100.0])
puts "Tested #{total_project_lines_tested}/#{total_project_lines} statements"
puts "Test Coverage: #{total_percentage}%"
end
end
end
end
================================================
FILE: lib/slather/coverage_service/sonarqube_xml_output.rb
================================================
require 'nokogiri'
require 'date'
module Slather
module CoverageService
module SonarqubeXmlOutput
def coverage_file_class
if input_format == "profdata"
Slather::ProfdataCoverageFile
else
Slather::CoverageFile
end
end
private :coverage_file_class
def post
cobertura_xml_report = create_xml_report(coverage_files)
store_report(cobertura_xml_report)
end
def store_report(report)
output_file = 'sonarqube-generic-coverage.xml'
if output_directory
FileUtils.mkdir_p(output_directory)
output_file = File.join(output_directory, output_file)
end
File.write(output_file, report.to_s)
end
def create_xml_report(coverage_files)
create_empty_xml_report
coverage_node = @doc.root
coverage_node['version'] = "1"
coverage_files.each do |coverage_file|
file_node = Nokogiri::XML::Node.new "file", @doc
file_node.parent = coverage_node
file_node['path'] = coverage_file.source_file_pathname_relative_to_repo_root.to_s
coverage_file.all_lines.each do |line|
if coverage_file.coverage_for_line(line)
line_node = Nokogiri::XML::Node.new "lineToCover", @doc
line_node['lineNumber'] = coverage_file.line_number_in_line(line)
line_node['covered'] = coverage_file.coverage_for_line(line) == 0 ? "false" : "true"
line_node.parent = file_node
end
end
end
@doc.to_xml
end
def create_empty_xml_report
builder = Nokogiri::XML::Builder.new do |xml|
xml.coverage
end
@doc = builder.doc
end
end
end
end
================================================
FILE: lib/slather/coveralls_coverage.rb
================================================
module Slather
module CoverallsCoverage
def as_json
{
:name => source_file_pathname_relative_to_repo_root.to_s,
:source => source_data,
:coverage => line_coverage_data
}
end
end
end
================================================
FILE: lib/slather/profdata_coverage_file.rb
================================================
require_relative 'coverage_info'
require_relative 'coveralls_coverage'
require 'digest/md5'
module Slather
class ProfdataCoverageFile
include CoverageInfo
include CoverallsCoverage
attr_accessor :project, :source, :segments, :line_numbers_first, :line_data
def initialize(project, source, line_numbers_first)
self.project = project
self.source = source
self.line_numbers_first = line_numbers_first
create_line_data
end
def create_line_data
line_data = Hash.new
all_lines.each { |line| line_data[line_number_in_line(line, self.line_numbers_first)] = line }
self.line_data = line_data
end
private :create_line_data
def path_on_first_line?
!source.lstrip.start_with?("1|")
end
def source_file_pathname
@source_file_pathname ||= begin
if path_on_first_line?
end_index = self.source.index(/:?\n/)
if end_index != nil
end_index -= 1
path = self.source[0..end_index]
else
# Empty file, output just contains path
path = self.source.sub ":", ""
end
path &&= Pathname(path)
else
# llvm-cov was run with just one matching source file
# It doesn't print the source path in this case, so we have to find it ourselves
# This is slow because we read every source file and compare it, but this should only happen if there aren't many source files
digest = Digest::MD5.digest(self.raw_source)
path = nil
project.find_source_files.each do |file|
file_digest = Digest::MD5.digest(File.read(file).strip)
if digest == file_digest
path = file
end
end
path
end
end
end
def source_file_pathname= (source_file_pathname)
@source_file_pathname = source_file_pathname
end
def source_file
File.new(source_file_pathname)
end
def source_code_lines
lines = self.source.split("\n")[(path_on_first_line? ? 1 : 0)..-1]
ignore_error_lines(lines)
end
def ignore_error_lines(lines, line_numbers_first = self.line_numbers_first)
if line_numbers_first
lines.reject { |line| line.lstrip.start_with?('|', '--') }
else
lines
end
end
def source_data
all_lines.join("\n")
end
def all_lines
@all_lines ||= source_code_lines
end
def raw_source
self.source.lines.map do |line|
line.split('|').last
end.join
end
def cleaned_gcov_data
source_data
end
def raw_data
self.source
end
def line_number_in_line(line, line_numbers_first = self.line_numbers_first)
if line_numbers_first
# Skip regex if the number is the first thing in the line
fastpath_number = line.to_i
return fastpath_number if fastpath_number != 0
line =~ /^(\s*)(\d*)/
group = $2
else
line =~ /^(\s*)(\d*)\|(\s*)(\d+)\|/
group = $4
end
if group != nil
match = group.strip
case match
when /[0-9]+/
return match.to_i
end
else
# llvm-cov outputs hit counts as 25.3k or 3.8M, so check this pattern as well
did_match = line =~ /^(\s*)(\d+\.\d+)(k|M)\|(\s*)(\d+)\|/
if did_match
match = $5.strip
case match
when /[0-9]+/
return match.to_i
end
end
end
0
end
def line_coverage_data
all_lines.map do |line|
coverage_for_line(line, self.line_numbers_first)
end
end
def coverage_for_line(line, line_numbers_first = self.line_numbers_first)
line = line.gsub(":", "|")
if line_numbers_first
line =~ /^(\s*)(\d*)\|(\s*)(\d+)\|/
group = $4
else
line =~ /^(\s*)(\d*)\|/
group = $2
end
if group == nil
# Check for thousands or millions (llvm-cov outputs hit counts as 25.3k or 3.8M)
if line_numbers_first
did_match = line =~ /^(\s*)(\d+)\|(\s*)(\d+\.\d+)(k|M)\|/
group = $4
units_group = $5
else
did_match = line =~ /^(\s*)(\d+\.\d+)(k|M)\|/
group = $2
units_group = $3
end
if did_match
count = group.strip
units = units_group == 'k' ? 1000 : 1000000
(count.to_f * units).to_i
else
return nil
end
else
match = group.strip
case match
when /[0-9]+/
match.to_i
when /#+/
0
when "-"
nil
end
end
end
def branch_coverage_data
@branch_coverage_data ||= begin
branch_coverage_data = Hash.new
self.segments.each do |segment|
line, col, hits, has_count, *rest = segment
next if !has_count
if branch_coverage_data.key?(line)
branch_coverage_data[line] = branch_coverage_data[line] + [hits]
else
branch_coverage_data[line] = [hits]
end
end
branch_coverage_data
end
end
def branch_region_data
@branch_region_data ||= begin
branch_region_data = Hash.new
region_start = nil
current_line = 0
@segments ||= []
@segments.each do |segment|
line, col, hits, has_count, *rest = segment
# Make column 0 based index
col = col - 1
if hits == 0 && has_count
current_line = line
region_start = col
elsif region_start != nil && hits > 0 && has_count
# if the region wrapped to a new line before ending, put nil to indicate it didnt end on this line
region_end = line == current_line ? col - region_start : nil
if branch_region_data.key?(current_line)
branch_region_data[current_line] << [region_start, region_end]
else
branch_region_data[current_line] = [[region_start, region_end]]
end
region_start = nil
end
end
branch_region_data
end
end
def source_file_basename
File.basename(source_file_pathname, '.swift')
end
def line_number_separator
"|"
end
def supported_file_extensions
["swift"]
end
private :supported_file_extensions
def ignored?
path = source_file_pathname.to_s
# This indicates a llvm-cov coverage warning (occurs if a passed in source file
# is not covered or with cache in some cases).
return true if path.end_with?("isn't covered.")
# Ignore source files inside of platform SDKs
return true if path.include?("/Xcode.*\.app\/Contents\/Developer\/Platforms")
super
end
end
end
================================================
FILE: lib/slather/project.rb
================================================
require 'fileutils'
require 'xcodeproj'
require 'json'
require 'yaml'
require 'shellwords'
module Xcodeproj
class Project
def slather_setup_for_coverage(format = :auto)
unless [:gcov, :clang, :auto].include?(format)
raise StandardError, "Only supported formats for setup are gcov, clang or auto"
end
if format == :auto
format = Slather.xcode_version[0] < 7 ? :gcov : :clang
end
build_configurations.each do |build_configuration|
if format == :clang
build_configuration.build_settings["CLANG_ENABLE_CODE_COVERAGE"] = "YES"
else
build_configuration.build_settings["GCC_INSTRUMENT_PROGRAM_FLOW_ARCS"] = "YES"
build_configuration.build_settings["GCC_GENERATE_TEST_COVERAGE_FILES"] = "YES"
end
end
# Patch xcschemes too
if format == :clang
schemes_path = Xcodeproj::XCScheme.shared_data_dir(self.path)
Xcodeproj::Project.schemes(self.path).each do |scheme_name|
xcscheme_path = "#{schemes_path + scheme_name}.xcscheme"
xcscheme = Xcodeproj::XCScheme.new(xcscheme_path)
xcscheme.test_action.xml_element.attributes['codeCoverageEnabled'] = 'YES'
xcscheme.save_as(self.path, scheme_name)
end
end
end
end
end
module Slather
class Project < Xcodeproj::Project
attr_accessor :build_directory, :ignore_list, :ci_service, :coverage_service, :coverage_access_token, :source_directory,
:output_directory, :xcodeproj, :show_html, :cdn_assets, :verbose_mode, :input_format, :scheme, :workspace, :binary_file, :binary_basename, :arch, :source_files,
:decimals, :llvm_version, :configuration
alias_method :setup_for_coverage, :slather_setup_for_coverage
def self.open(xcodeproj)
proj = super
proj.xcodeproj = xcodeproj
proj
end
def failure_help_string
"\n\tAre you sure your project is generating coverage? Make sure you enable code coverage in the Test section of your Xcode scheme.\n\tDid you specify your Xcode scheme? (--scheme or 'scheme' in .slather.yml)\n\tIf you're using a workspace, did you specify it? (--workspace or 'workspace' in .slather.yml)\n\tIf you use a different Xcode configuration, did you specify it? (--configuration or 'configuration' in .slather.yml)"
end
def derived_data_path
# Get the derived data path from xcodebuild
# Use OBJROOT when possible, as it provides regardless of whether or not the Derived Data location is customized
if self.workspace
projectOrWorkspaceArgument = "-workspace \"#{self.workspace}\""
else
projectOrWorkspaceArgument = "-project \"#{self.path}\""
end
if self.scheme
schemeArgument = "-scheme \"#{self.scheme}\""
buildAction = "test"
else
schemeArgument = nil
buildAction = nil
end
# redirect stderr to avoid xcodebuild errors being printed.
build_settings = `xcodebuild #{projectOrWorkspaceArgument} #{schemeArgument} -showBuildSettings #{buildAction} CODE_SIGNING_ALLOWED=NO CODE_SIGNING_REQUIRED=NO 2>&1`
if build_settings
derived_data_path = build_settings.match(/ OBJROOT = (.+)/)
# when match fails derived_data_path is nil
derived_data_path = derived_data_path[1] if derived_data_path
end
if derived_data_path == nil
derived_data_path = File.expand_path('~') + "/Library/Developer/Xcode/DerivedData/"
end
derived_data_path
end
private :derived_data_path
def coverage_files
if self.input_format == "profdata"
profdata_coverage_files
else
gcov_coverage_files
end
end
def gcov_coverage_files
coverage_files = Dir["#{build_directory}/**/*.gcno"].map do |file|
coverage_file = coverage_file_class.new(self, file)
# If there's no source file for this gcno, it probably belongs to another project.
coverage_file.source_file_pathname && !coverage_file.ignored? ? coverage_file : nil
end.compact
if coverage_files.empty?
raise StandardError, "No coverage files found."
else
dedupe(coverage_files)
end
end
private :gcov_coverage_files
def profdata_coverage_files
coverage_files = []
if self.binary_file
self.binary_file.each do |binary_path|
pathnames_per_binary = pathnames_per_binary(binary_path)
coverage_files.concat(create_coverage_files_for_binary(binary_path, pathnames_per_binary))
end
end
if coverage_files.empty?
raise StandardError, "No coverage files found."
else
dedupe(coverage_files)
end
end
private :profdata_coverage_files
def pathnames_per_binary(binary_path)
coverage_json_string = llvm_cov_export_output(binary_path)
if coverage_json_string.strip != ""
# JSON.parse will crash on an empty string, so just skip everything if the string is empty.
coverage_json = JSON.parse(coverage_json_string)
coverage_json["data"].reduce([]) do |result, chunk|
result.concat(chunk["files"].map do |file|
filename = file["filename"]
path = Pathname(filename)
# Don't crash if the file doesn't exist on disk.
# This may happen for autogenerated files that have been deleted.
filename = path.exist? ? path.realpath : filename
{"filename" => filename, "segments" => file["segments"]}
end)
end
end
end
private :pathnames_per_binary
def create_coverage_files_for_binary(binary_path, pathnames_per_binary)
return [] unless pathnames_per_binary != nil
coverage_files = []
begin
coverage_files.concat(create_coverage_files(binary_path, pathnames_per_binary))
rescue Errno::E2BIG => e
# pathnames_per_binary is too big for the OS to handle so it's split in two halfs which are processed independently
if pathnames_per_binary.count > 1
left, right = pathnames_per_binary.each_slice( (pathnames_per_binary.size/2.0).round ).to_a
coverage_files.concat(create_coverage_files_for_binary(binary_path, left))
coverage_files.concat(create_coverage_files_for_binary(binary_path, right))
else
# pathnames_per_binary contains one element which is too big for the OS to handle.
raise e, "#{e}. A path in your project is close to the E2BIG limit. https://github.com/SlatherOrg/slather/pull/414", e.backtrace
end
end
coverage_files
end
private :create_coverage_files_for_binary
def create_coverage_files(binary_path, path_objects)
line_numbers_first = Gem::Version.new(self.llvm_version) >= Gem::Version.new('8.1.0')
# get just file names from the path objects
pathnames = path_objects.map { |path_obj| path_obj["filename"] }.compact
# Map of path name => segment array
paths_to_segments = path_objects.reduce(Hash.new) do |hash, path_obj|
hash[path_obj["filename"]] = path_obj["segments"]
hash
end
files = create_profdata(binary_path, pathnames)
files.map do |source|
coverage_file = coverage_file_class.new(self, source, line_numbers_first)
# If a single source file is used, the resulting output does not contain the file name.
coverage_file.source_file_pathname = pathnames.first if pathnames.count == 1
# if there is segment data for the given path, add it to the coverage_file
if paths_to_segments.key?(coverage_file.source_file_pathname)
coverage_file.segments = paths_to_segments[coverage_file.source_file_pathname]
end
coverage_file.source_file_pathname && !coverage_file.ignored? && coverage_file.include_file? ? coverage_file : nil
end.compact
end
private :create_coverage_files
def create_profdata(binary_path, pathnames)
profdata_llvm_cov_output(binary_path, pathnames).split("\n\n")
end
private :create_profdata
def remove_extension(path)
path.split(".")[0..-2].join(".")
end
def first_product_name
first_product = self.products.first
# If name is not available it computes it using
# the path by dropping the 'extension' of the path.
first_product.name || remove_extension(first_product.path)
end
def profdata_coverage_dir
@profdata_coverage_dir ||= begin
raise StandardError, "The specified build directory (#{self.build_directory}) does not exist" unless File.exist?(self.build_directory)
dir = nil
if self.scheme
dir = Dir[File.join(build_directory,"/**/CodeCoverage/#{self.scheme}")].first
else
dir = Dir[File.join(build_directory,"/**/#{first_product_name}")].first
end
if dir == nil
# Xcode 7.3 moved the location of Coverage.profdata
dir = Dir[File.join(build_directory,"/**/CodeCoverage")].first
end
if dir == nil && Slather.xcode_version[0] >= 9
# Xcode 9 moved the location of Coverage.profdata
coverage_files = Dir[File.join(build_directory, "/**/ProfileData/*/Coverage.profdata")]
if coverage_files.count == 0
# Look up one directory
# The ProfileData directory is next to Intermediates.noindex (in previous versions of Xcode the coverage was inside Intermediates)
coverage_files = Dir[File.join(build_directory, "../**/ProfileData/*/Coverage.profdata")]
end
if coverage_files != nil && coverage_files.count != 0
dir = Pathname.new(coverage_files.first).parent()
end
end
raise StandardError, "No coverage directory found." unless dir != nil
dir
end
end
def profdata_file
profdata_coverage_dir = self.profdata_coverage_dir
if profdata_coverage_dir == nil
raise StandardError, "No coverage directory found. Please make sure the \"Code Coverage\" checkbox is enabled in your scheme's Test action or the build_directory property is set."
end
file = Dir["#{profdata_coverage_dir}/**/Coverage.profdata"].first
unless file != nil
return nil
end
return File.expand_path(file)
end
private :profdata_file
def unsafe_llvm_cov_export_output(binary_path)
profdata_file_arg = profdata_file
if profdata_file_arg == nil
raise StandardError, "No Coverage.profdata files found. Please make sure the \"Code Coverage\" checkbox is enabled in your scheme's Test action or the build_directory property is set."
end
if binary_path == nil
raise StandardError, "No binary file found."
end
llvm_cov_args = %W(export -instr-profile #{profdata_file_arg} #{binary_path})
if self.arch
llvm_cov_args << "--arch" << self.arch
end
`xcrun llvm-cov #{llvm_cov_args.shelljoin}`
end
private :unsafe_llvm_cov_export_output
def llvm_cov_export_output(binary_path)
output = unsafe_llvm_cov_export_output(binary_path)
output.valid_encoding? ? output : output.encode!('UTF-8', 'binary', :invalid => :replace, undef: :replace)
end
private :llvm_cov_export_output
def unsafe_profdata_llvm_cov_output(binary_path, source_files)
profdata_file_arg = profdata_file
if profdata_file_arg == nil
raise StandardError, "No Coverage.profdata files found. Please make sure the \"Code Coverage\" checkbox is enabled in your scheme's Test action or the build_directory property is set."
end
if binary_path == nil
raise StandardError, "No binary file found."
end
llvm_cov_args = %W(show -instr-profile #{profdata_file_arg} #{binary_path})
if self.arch
llvm_cov_args << "--arch" << self.arch
end
# 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".
# Using the xargs command we can break the list of source_files into sublists small enough to be acceptable.
`printf '%s\\0' #{source_files.shelljoin} | xargs -0 xcrun llvm-cov #{llvm_cov_args.shelljoin}`
end
private :unsafe_profdata_llvm_cov_output
def profdata_llvm_cov_output(binary_path, source_files)
output = unsafe_profdata_llvm_cov_output(binary_path, source_files)
output.valid_encoding? ? output : output.encode!('UTF-8', 'binary', :invalid => :replace, undef: :replace)
end
private :profdata_llvm_cov_output
def dedupe(coverage_files)
coverage_files.group_by(&:source_file_pathname).values.map { |cf_array| cf_array.max_by(&:percentage_lines_tested) }
end
private :dedupe
@@ymlfile = '.slather.yml'
def self.yml_filename=(var)
@@ymlfile = var
end
def self.yml_filename
@@ymlfile
end
def self.yml
@yml ||= File.exist?(yml_filename) ? YAML.load_file(yml_filename) : {}
end
def configure
begin
configure_scheme
configure_configuration
configure_workspace
configure_build_directory
configure_ignore_list
configure_ci_service
configure_coverage_access_token
configure_coverage_service
configure_source_directory
configure_output_directory
configure_input_format
configure_arch
configure_binary_file
configure_decimals
configure_source_files
self.llvm_version = `xcrun llvm-cov --version`.match(/LLVM version ([\d\.]+)/).captures[0]
rescue => e
puts e.message
puts failure_help_string
puts "\n"
raise
end
if self.verbose_mode
puts "\nProcessing coverage file: #{profdata_file}"
if self.binary_file
puts "Against binary files:"
self.binary_file.each do |binary_file|
puts "\t#{binary_file}"
end
else
puts "No binary files found."
end
puts "\n"
end
end
def configure_build_directory
self.build_directory ||= self.class.yml["build_directory"] || derived_data_path
end
def configure_source_directory
self.source_directory ||= self.class.yml["source_directory"] if self.class.yml["source_directory"]
end
def configure_output_directory
self.output_directory ||= self.class.yml["output_directory"] if self.class.yml["output_directory"]
end
def configure_ignore_list
self.ignore_list ||= [(self.class.yml["ignore"] || [])].flatten
end
def configure_source_files
self.source_files ||= [(self.class.yml["source_files"] || [])].flatten
end
def configure_ci_service
self.ci_service ||= (ENV["CI_SERVICE"] || self.class.yml["ci_service"] || :other)
end
def configure_input_format
self.input_format ||= (self.class.yml["input_format"] || "auto")
end
def input_format=(format)
format ||= "auto"
unless %w(gcov profdata auto).include?(format)
raise StandardError, "Only supported input formats are gcov, profdata or auto"
end
if format == "auto"
@input_format = Slather.xcode_version[0] < 7 ? "gcov" : "profdata"
else
@input_format = format
end
end
def configure_scheme
self.scheme ||= self.class.yml["scheme"] if self.class.yml["scheme"]
end
def configure_configuration
self.configuration ||= self.class.yml["configuration"] if self.class.yml["configuration"]
end
def configure_decimals
return if self.decimals
self.decimals ||= self.class.yml["decimals"] if self.class.yml["decimals"]
self.decimals = self.decimals ? Integer(self.decimals) : 2
end
def configure_workspace
self.workspace ||= self.class.yml["workspace"] if self.class.yml["workspace"]
end
def ci_service=(service)
@ci_service = service && service.to_sym
end
def configure_coverage_service
self.coverage_service ||= (self.class.yml["coverage_service"] || :terminal)
end
def configure_coverage_access_token
self.coverage_access_token ||= (ENV["COVERAGE_ACCESS_TOKEN"] || self.class.yml["coverage_access_token"] || "")
end
def coverage_service=(service)
service = service && service.to_sym
case service
when :coveralls
extend(Slather::CoverageService::Coveralls)
when :hardcover
extend(Slather::CoverageService::Hardcover)
when :terminal
extend(Slather::CoverageService::SimpleOutput)
when :gutter_json
extend(Slather::CoverageService::GutterJsonOutput)
when :cobertura_xml
extend(Slather::CoverageService::CoberturaXmlOutput)
when :llvm_cov
extend(Slather::CoverageService::LlvmCovOutput)
when :html
extend(Slather::CoverageService::HtmlOutput)
when :json
extend(Slather::CoverageService::JsonOutput)
when :sonarqube_xml
extend(Slather::CoverageService::SonarqubeXmlOutput)
else
raise ArgumentError, "`#{coverage_service}` is not a valid coverage service. Try `terminal`, `coveralls`, `gutter_json`, `cobertura_xml` or `html`"
end
@coverage_service = service
end
def configure_binary_file
if self.input_format == "profdata"
self.binary_file = load_option_array("binary_file") || find_binary_files
end
end
def configure_arch
self.arch ||= self.class.yml["arch"] if self.class.yml["arch"]
end
def decimal_f decimal_arg
configure_decimals unless decimals
decimal = "%.#{decimals}f" % decimal_arg
return decimal if decimals == 2 # special case 2 for backwards compatibility
decimal.to_f.to_s
end
def find_binary_file_in_bundle(bundle_file)
if File.directory? bundle_file
bundle_file_noext = File.basename(bundle_file, File.extname(bundle_file))
# Search for .debug.dylib binaries
# See https://developer.apple.com/documentation/xcode/build-settings-reference#Enable-Debug-Dylib-Support for details
debug_dylib_matches = Dir["#{bundle_file}/**/#{bundle_file_noext}.debug.dylib"]
if debug_dylib_matches.length() > 0
debug_dylib_matches.first
else
Dir["#{bundle_file}/**/#{bundle_file_noext}"].first
end
else
bundle_file
end
end
def find_binary_files
binary_basename = load_option_array("binary_basename")
found_binaries = []
# Get scheme info out of the xcodeproj
if self.scheme
schemes_path = Xcodeproj::XCScheme.shared_data_dir(self.path)
xcscheme_path = "#{schemes_path + self.scheme}.xcscheme"
# Try to look inside 'xcuserdata' if the scheme is not found in 'xcshareddata'
if !File.file?(xcscheme_path)
schemes_path = Xcodeproj::XCScheme.user_data_dir(self.path)
xcscheme_path = "#{schemes_path + self.scheme}.xcscheme"
end
if self.workspace and !File.file?(xcscheme_path)
# No scheme was found in the xcodeproj, check the workspace
schemes_path = Xcodeproj::XCScheme.shared_data_dir(self.workspace)
xcscheme_path = "#{schemes_path + self.scheme}.xcscheme"
if !File.file?(xcscheme_path)
schemes_path = Xcodeproj::XCScheme.user_data_dir(self.workspace)
xcscheme_path = "#{schemes_path + self.scheme}.xcscheme"
end
end
raise StandardError, "No scheme named '#{self.scheme}' found in #{self.path}" unless File.exist? xcscheme_path
xcscheme = Xcodeproj::XCScheme.new(xcscheme_path)
if self.configuration
configuration = self.configuration
else
configuration = xcscheme.test_action.build_configuration
end
search_list = binary_basename || find_buildable_names(xcscheme)
search_dir = profdata_coverage_dir
if Slather.xcode_version[0] >= 9
# Go from the directory containing Coverage.profdata back to the directory containing Products (back out of ProfileData/UUID-dir)
search_dir = File.join(search_dir, '../..')
end
search_list.each do |search_for|
found_product = Dir["#{search_dir}/Products/#{configuration}*/#{search_for}*"].sort { |x, y|
# Sort the matches without the file extension to ensure better matches when there are multiple candidates
# For example, if the binary_basename is Test then we want Test.app to be matched before Test Helper.app
File.basename(x, File.extname(x)) <=> File.basename(y, File.extname(y))
}.find { |path|
next if path.end_with? ".dSYM"
next if path.end_with? ".swiftmodule"
if File.directory? path
path = find_binary_file_in_bundle(path)
next if path.nil?
end
matches_arch(path)
}
if found_product and File.directory? found_product
found_binary = find_binary_file_in_bundle(found_product)
else
found_binary = found_product
end
if found_binary
found_binaries.push(found_binary)
end
end
else
xctest_bundle = Dir["#{profdata_coverage_dir}/**/*.xctest"].reject { |bundle|
# Ignore xctest bundles that are in the UI runner app
bundle.include? "-Runner.app/PlugIns/"
}.first
# Find the matching binary file
search_list = binary_basename || ['*']
search_list.each do |search_for|
xctest_bundle_file_directory = Pathname.new(xctest_bundle).dirname
app_bundle = Dir["#{xctest_bundle_file_directory}/#{search_for}.app"].first
matched_xctest_bundle = Dir["#{xctest_bundle_file_directory}/#{search_for}.xctest"].first
dynamic_lib_bundle = Dir["#{xctest_bundle_file_directory}/#{search_for}.{framework,dylib}"].first
if app_bundle != nil
found_binary = find_binary_file_in_bundle(app_bundle)
elsif matched_xctest_bundle != nil
found_binary = find_binary_file_in_bundle(matched_xctest_bundle)
elsif dynamic_lib_bundle != nil
found_binary = find_binary_file_in_bundle(dynamic_lib_bundle)
else
found_binary = find_binary_file_in_bundle(xctest_bundle)
end
if found_binary
found_binaries.push(found_binary)
end
end
end
raise StandardError, "No product binary found in #{profdata_coverage_dir}." unless found_binaries.count > 0
found_binaries.map { |binary| File.expand_path(binary) }
end
def find_buildable_names(xcscheme)
found_buildable_names = []
# enumerate code coverage targets
begin
code_coverage_targets = xcscheme.test_action.xml_element.elements['CodeCoverageTargets']
targets = code_coverage_targets.map do |node|
Xcodeproj::XCScheme::BuildableReference.new(node) if node.is_a?(REXML::Element)
end.compact
buildable_names = targets.each do |target|
found_buildable_names.push(target.buildable_name)
end
rescue
# just in case if there are no entries in the test action
end
# enumerate build action entries
begin
xcscheme.build_action.entries.each do |entry|
buildable_name = entry.buildable_references[0].buildable_name
if !buildable_name.end_with? ".a"
# Can't run code coverage on static libraries
found_buildable_names.push(buildable_name)
end
end
rescue
# xcodeproj will raise an exception if there are no entries in the build action
end
# enumerate test action entries
begin
xcscheme.test_action.testables.each do |entry|
buildable_name = entry.buildable_references[0].buildable_name
found_buildable_names.push(buildable_name)
end
rescue
# just in case if there are no entries in the test action
end
# some items are both buildable and testable, so return only unique ones
found_buildable_names.uniq
end
def matches_arch(binary_path)
if self.arch
lipo_output = `lipo -info "#{binary_path}"`
archs_in_binary = lipo_output.split(':').last.split(' ')
archs_in_binary.include? self.arch
else
true
end
end
def find_source_files
source_files = load_option_array("source_files")
return [] if source_files.nil?
current_dir = Pathname("./").realpath
paths = source_files.flat_map { |pattern| Dir.glob(pattern) }.uniq
paths.map do |path|
source_file_absolute_path = Pathname(path).realpath
source_file_relative_path = source_file_absolute_path.relative_path_from(current_dir)
self.ignore_list.any? { |ignore| File.fnmatch(ignore, source_file_relative_path) } ? nil : source_file_absolute_path
end.compact
end
def load_option_array(option)
value = self.send(option.to_sym)
# Only load if a value is not already set
if !value
value_yml = self.class.yml[option]
# Need to check the type in the config file because it can be a string or array
if value_yml and value_yml.is_a? Array
value = value_yml
elsif value_yml
value = [value_yml]
end
end
value
end
end
end
================================================
FILE: lib/slather/version.rb
================================================
module Slather
VERSION = '2.8.5' unless defined?(Slather::VERSION)
end
================================================
FILE: lib/slather.rb
================================================
require_relative 'slather/version'
require_relative 'slather/project'
require_relative 'slather/coverage_info'
require_relative 'slather/coverage_file'
require_relative 'slather/coveralls_coverage'
require_relative 'slather/profdata_coverage_file'
require_relative 'slather/coverage_service/cobertura_xml_output'
require_relative 'slather/coverage_service/coveralls'
require_relative 'slather/coverage_service/hardcover'
require_relative 'slather/coverage_service/gutter_json_output'
require_relative 'slather/coverage_service/simple_output'
require_relative 'slather/coverage_service/html_output'
require_relative 'slather/coverage_service/json_output'
require_relative 'slather/coverage_service/llvm_cov_output'
require_relative 'slather/coverage_service/sonarqube_xml_output'
require 'cfpropertylist'
module Slather
Encoding.default_external = "utf-8"
def self.prepare_pods(pods)
Pod::UI.warn("[Slather] prepare_pods is now deprecated. The call to prepare_pods in your Podfile can simply be ommitted.")
end
def self.xcode_version
xcode_path = `xcode-select -p`.strip
plist = CFPropertyList::List.new(:file => File.join(xcode_path, '..', 'Info.plist'))
xcode_version = CFPropertyList.native_types(plist.value)["CFBundleShortVersionString"]
xcode_version.split('.').map(&:to_i)
end
end
================================================
FILE: slather.gemspec
================================================
# encoding: utf-8
lib = File.expand_path('../lib', __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'slather/version'
Gem::Specification.new do |spec|
spec.name = 'slather'
spec.version = Slather::VERSION
spec.authors = ['Mark Larsen']
spec.email = ['mark@venmo.com']
spec.summary = %q{Test coverage reports for Xcode projects}
spec.homepage = 'https://github.com/SlatherOrg/slather'
spec.license = 'MIT'
spec.files = `git ls-files -z`.force_encoding('utf-8').split("\x0")
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
spec.require_paths = ['lib']
spec.add_development_dependency 'bundler', '~> 2.0'
spec.add_development_dependency 'coveralls', '~> 0.8'
spec.add_development_dependency 'simplecov', '~> 0'
spec.add_development_dependency 'rake', '~> 12.3'
spec.add_development_dependency 'rspec', '~> 3.8'
spec.add_development_dependency 'pry', '~> 0.12'
spec.add_development_dependency 'cocoapods', '~> 1.10.beta.1'
spec.add_development_dependency 'json_spec', '~> 1.1'
spec.add_development_dependency 'equivalent-xml', '~> 0.6'
spec.add_dependency 'clamp', '~> 1.3'
spec.add_dependency 'xcodeproj', '~> 1.27'
spec.add_dependency 'nokogiri', '>= 1.14.3'
spec.add_dependency 'CFPropertyList', '>= 2.2', '< 4'
spec.add_runtime_dependency 'activesupport'
end
================================================
FILE: spec/fixtures/FixtureFramework/FixtureFramework.h
================================================
//
// FixtureFramework.h
// FixtureFramework
//
// Created by Stephen Williams on 11/03/21.
// Copyright © 2021 marklarr. All rights reserved.
//
#import <Foundation/Foundation.h>
//! Project version number for FixtureFramework.
FOUNDATION_EXPORT double FixtureFrameworkVersionNumber;
//! Project version string for FixtureFramework.
FOUNDATION_EXPORT const unsigned char FixtureFrameworkVersionString[];
// In this header, you should import all the public headers of your framework using statements like #import <FixtureFramework/PublicHeader.h>
================================================
FILE: spec/fixtures/FixtureFramework/FlashExperiment.swift
================================================
import Foundation
public struct FlashExperiment {
public let isAwesome = true
public init() {}
}
================================================
FILE: spec/fixtures/FixtureFramework/Info.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2021 marklarr. All rights reserved.</string>
</dict>
</plist>
================================================
FILE: spec/fixtures/FixtureFrameworkTests/FixtureFrameworkTests.swift
================================================
//
// FixtureFrameworkTests.swift
// FixtureFrameworkTests
//
// Created by Stephen Williams on 11/03/21.
// Copyright © 2021 marklarr. All rights reserved.
//
import XCTest
@testable import FixtureFramework
class FixtureFrameworkTests: XCTestCase {
override func setUpWithError() throws {
// Put setup code here. This method is called before the invocation of each test method in the class.
}
override func tearDownWithError() throws {
// Put teardown code here. This method is called after the invocation of each test method in the class.
}
func testExample() throws {
// This is an example of a functional test case.
// Use XCTAssert and related functions to verify your tests produce the correct results.
}
func testPerformanceExample() throws {
// This is an example of a performance test case.
self.measure {
// Put the code you want to measure the time of here.
}
}
}
================================================
FILE: spec/fixtures/FixtureFrameworkTests/FlashExperimentTests.swift
================================================
import XCTest
import FixtureFramework
class FlashExperimentTests: XCTestCase {
func testExample() throws {
let sut = FlashExperiment()
XCTAssertTrue(sut.isAwesome, "Your flash experiment isn't awesome!")
}
}
================================================
FILE: spec/fixtures/FixtureFrameworkTests/Info.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
</dict>
</plist>
================================================
FILE: spec/fixtures/fixtures/Fixtures.swift
================================================
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
return true
}
func applicationWillResignActive(application: UIApplication) {
}
}
================================================
FILE: spec/fixtures/fixtures/Supporting Files/fixtures-Prefix.pch
================================================
//
// Prefix header
//
// The contents of this file are implicitly included at the beginning of every source file.
//
#ifdef __OBJC__
#import <Cocoa/Cocoa.h>
#endif
================================================
FILE: spec/fixtures/fixtures/fixtures.h
================================================
//
// fixtures.h
// fixtures
//
// Created by Mark Larsen on 6/24/14.
// Copyright (c) 2014 marklarr. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface fixtures : NSObject
- (void)testedMethod;
- (void)untestedMethod;
@end
================================================
FILE: spec/fixtures/fixtures/fixtures.m
================================================
//
// fixtures.m
// fixtures
//
// Created by Mark Larsen on 6/24/14.
// Copyright (c) 2014 marklarr 🌟. All rights reserved.
//
#import "fixtures.h"
@implementation fixtures
- (void)testedMethod
{
NSLog(@"tested");
}
- (void)untestedMethod
{
NSLog(@"untested");
}
@end
================================================
FILE: spec/fixtures/fixtures/fixtures_cpp.cpp
================================================
//
// fixtures_cpp.cpp
// fixtures
//
// Created by Larsen, Mark on 4/3/15.
// Copyright (c) 2015 marklarr. All rights reserved.
//
#include "fixtures_cpp.h"
================================================
FILE: spec/fixtures/fixtures/fixtures_cpp.h
================================================
#ifndef __fixtures__fixtures_cpp__
#define __fixtures__fixtures_cpp__
#include <stdio.h>
#endif /* defined(__fixtures__fixtures_cpp__) */
================================================
FILE: spec/fixtures/fixtures/fixtures_m.h
================================================
#import <Foundation/Foundation.h>
@interface fixtures_m : NSObject
@end
================================================
FILE: spec/fixtures/fixtures/fixtures_m.m
================================================
#import "fixtures_m.h"
@implementation fixtures_m
@end
================================================
FILE: spec/fixtures/fixtures/fixtures_mm.h
================================================
#import <Foundation/Foundation.h>
@interface fixtures_mm : NSObject
@end
================================================
FILE: spec/fixtures/fixtures/fixtures_mm.mm
================================================
#import "fixtures_mm.h"
@implementation fixtures_mm
@end
================================================
FILE: spec/fixtures/fixtures/more_files/Branches.h
================================================
//
// Branches.h
// fixtures
//
// Created by Julian Krumow on 11.10.14.
// Copyright (c) 2014 marklarr. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface Branches : NSObject
- (void)branches:(BOOL)goIf skipBranches:(BOOL)skipBranches;
@end
================================================
FILE: spec/fixtures/fixtures/more_files/Branches.m
================================================
//
// Branches.m
// fixtures
//
// Created by Julian Krumow on 11.10.14.
// Copyright (c) 2014 marklarr. All rights reserved.
//
#import "Branches.h"
@implementation Branches
- (void)branches:(BOOL)goIf skipBranches:(BOOL)skipBranches
{
if (goIf) {
NSLog(@"foo.");
if (!skipBranches) {
NSLog(@"not skipped.");
}
} else {
NSLog(@"bar.");
}
int i = 5;
if (i == 5) {
return;
}
switch (i) {
case 0:
NSLog(@"0");
break;
case 1:
NSLog(@"1");
break;
case 5:
NSLog(@"5");
break;
default:
break;
}
}
@end
================================================
FILE: spec/fixtures/fixtures/more_files/Empty.h
================================================
//
// Empty.h
// fixtures
//
// Created by Julian Krumow on 27.10.14.
// Copyright (c) 2014 marklarr. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface Empty : NSObject
@end
================================================
FILE: spec/fixtures/fixtures/more_files/Empty.m
================================================
//
// Empty.m
// fixtures
//
// Created by Julian Krumow on 27.10.14.
// Copyright (c) 2014 marklarr. All rights reserved.
//
#import "Empty.h"
@implementation Empty
@end
================================================
FILE: spec/fixtures/fixtures/more_files/peekaview.h
================================================
//
// peekaview.h
// fixtures
//
// Created by Mark Larsen on 6/25/14.
// Copyright (c) 2014 marklarr. All rights reserved.
//
#import <AppKit/AppKit.h>
@interface peekaview : NSView
@end
================================================
FILE: spec/fixtures/fixtures/more_files/peekaview.m
================================================
//
// peekaview.m
// fixtures
//
// Created by Mark Larsen on 6/25/14.
// Copyright (c) 2014 marklarr. All rights reserved.
//
#import "peekaview.h"
@implementation peekaview
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
// Drawing code
}
*/
@end
================================================
FILE: spec/fixtures/fixtures/other_fixtures.m
================================================
//
// other_fixtures.m
// fixtures
//
// Created by Mark Larsen on 6/24/14.
// Copyright (c) 2014 marklarr. All rights reserved.
//
#import "other_fixtures.h"
@implementation other_fixtures
- (void)testedMethod
{
NSLog(@"tested");
}
- (void)untestedMethod
{
NSLog(@"untested");
}
@end
================================================
FILE: spec/fixtures/fixtures.xcodeproj/project.pbxproj
================================================
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
155BBCA519E9CB6700BACB13 /* Branches.h in Headers */ = {isa = PBXBuildFile; fileRef = 155BBCA319E9CB6700BACB13 /* Branches.h */; };
155BBCA619E9CB6700BACB13 /* Branches.m in Sources */ = {isa = PBXBuildFile; fileRef = 155BBCA419E9CB6700BACB13 /* Branches.m */; };
155BBCA819E9CCC500BACB13 /* BranchesTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 155BBCA719E9CCC500BACB13 /* BranchesTests.m */; };
155D8AFE19FED984004666BA /* Empty.h in Headers */ = {isa = PBXBuildFile; fileRef = 155D8AFC19FED984004666BA /* Empty.h */; };
155D8AFF19FED984004666BA /* Empty.m in Sources */ = {isa = PBXBuildFile; fileRef = 155D8AFD19FED984004666BA /* Empty.m */; };
3773307C1CC42A58005EAF65 /* fixturesTwo.h in Headers */ = {isa = PBXBuildFile; fileRef = 3773307B1CC42A58005EAF65 /* fixturesTwo.h */; };
3773307E1CC42A58005EAF65 /* fixturesTwo.m in Sources */ = {isa = PBXBuildFile; fileRef = 3773307D1CC42A58005EAF65 /* fixturesTwo.m */; };
377330821CC42ABF005EAF65 /* libfixturesTwo.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 377330791CC42A58005EAF65 /* libfixturesTwo.dylib */; };
8554482F1E461FAF0032518E /* fixturesTestsSecond.m in Sources */ = {isa = PBXBuildFile; fileRef = 8554482E1E461FAF0032518E /* fixturesTestsSecond.m */; };
85AE69041E45F0F900DA2D47 /* libfixtures.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8C9A202D195965F10013B6B3 /* libfixtures.a */; };
85AE69051E45F0F900DA2D47 /* libfixturesTwo.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 377330791CC42A58005EAF65 /* libfixturesTwo.dylib */; };
85AE69061E45F0F900DA2D47 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8C9A2030195965F10013B6B3 /* Cocoa.framework */; };
85AE69081E45F0F900DA2D47 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 8C9A204A195965F10013B6B3 /* InfoPlist.strings */; };
8C0F0B401ACF43A300793B7D /* fixtures_m.h in Headers */ = {isa = PBXBuildFile; fileRef = 8C0F0B3E1ACF43A300793B7D /* fixtures_m.h */; };
8C0F0B411ACF43A300793B7D /* fixtures_m.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C0F0B3F1ACF43A300793B7D /* fixtures_m.m */; };
8C0F0B441ACF44E000793B7D /* fixtures_cpp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8C0F0B421ACF44E000793B7D /* fixtures_cpp.cpp */; };
8C0F0B451ACF44E000793B7D /* fixtures_cpp.h in Headers */ = {isa = PBXBuildFile; fileRef = 8C0F0B431ACF44E000793B7D /* fixtures_cpp.h */; };
8C0F0B481ACF44F200793B7D /* fixtures_mm.h in Headers */ = {isa = PBXBuildFile; fileRef = 8C0F0B461ACF44F200793B7D /* fixtures_mm.h */; };
8C0F0B491ACF44F200793B7D /* fixtures_mm.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8C0F0B471ACF44F200793B7D /* fixtures_mm.mm */; };
8C52AEF7195AAE32008A882A /* peekaview.h in Headers */ = {isa = PBXBuildFile; fileRef = 8C52AEF5195AAE32008A882A /* peekaview.h */; };
8C52AEF8195AAE33008A882A /* peekaview.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C52AEF6195AAE32008A882A /* peekaview.m */; };
8C52AEFA195AAE70008A882A /* peekaviewTests💣.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C52AEF9195AAE70008A882A /* peekaviewTests💣.m */; };
8C9A2031195965F10013B6B3 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8C9A2030195965F10013B6B3 /* Cocoa.framework */; };
8C9A203B195965F10013B6B3 /* fixtures.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C9A203A195965F10013B6B3 /* fixtures.m */; };
8C9A2043195965F10013B6B3 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8C9A2030195965F10013B6B3 /* Cocoa.framework */; };
8C9A2046195965F10013B6B3 /* libfixtures.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8C9A202D195965F10013B6B3 /* libfixtures.a */; };
8C9A204C195965F10013B6B3 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 8C9A204A195965F10013B6B3 /* InfoPlist.strings */; };
8C9A204E195965F10013B6B3 /* fixturesTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C9A204D195965F10013B6B3 /* fixturesTests.m */; };
B1E6981225F96B680086A3E2 /* FixtureFramework.h in Headers */ = {isa = PBXBuildFile; fileRef = B1E6980425F96B670086A3E2 /* FixtureFramework.h */; settings = {ATTRIBUTES = (Public, ); }; };
B1E6982025F96B930086A3E2 /* FlashExperiment.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1E6981F25F96B930086A3E2 /* FlashExperiment.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
85AE68FE1E45F0F900DA2D47 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 8C9A2025195965F00013B6B3 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 8C9A202C195965F10013B6B3;
remoteInfo = fixtures;
};
8C9A2044195965F10013B6B3 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 8C9A2025195965F00013B6B3 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 8C9A202C195965F10013B6B3;
remoteInfo = fixtures;
};
B1E6982F25F96F490086A3E2 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 8C9A2025195965F00013B6B3 /* Project object */;
proxyType = 1;
remoteGlobalIDString = B1E6980125F96B670086A3E2;
remoteInfo = FixtureFramework;
};
B1E6983725F970320086A3E2 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 8C9A2025195965F00013B6B3 /* Project object */;
proxyType = 1;
remoteGlobalIDString = B1E6980125F96B670086A3E2;
remoteInfo = FixtureFramework;
};
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
155BBCA319E9CB6700BACB13 /* Branches.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Branches.h; sourceTree = "<group>"; };
155BBCA419E9CB6700BACB13 /* Branches.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Branches.m; sourceTree = "<group>"; };
155BBCA719E9CCC500BACB13 /* BranchesTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BranchesTests.m; sourceTree = "<group>"; };
155D8AFC19FED984004666BA /* Empty.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Empty.h; sourceTree = "<group>"; };
155D8AFD19FED984004666BA /* Empty.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Empty.m; sourceTree = "<group>"; };
377330791CC42A58005EAF65 /* libfixturesTwo.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libfixturesTwo.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
3773307B1CC42A58005EAF65 /* fixturesTwo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = fixturesTwo.h; sourceTree = "<group>"; };
3773307D1CC42A58005EAF65 /* fixturesTwo.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = fixturesTwo.m; sourceTree = "<group>"; };
8554482E1E461FAF0032518E /* fixturesTestsSecond.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = fixturesTestsSecond.m; sourceTree = "<group>"; };
85AE690C1E45F0F900DA2D47 /* fixturesTestsSecond.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = fixturesTestsSecond.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
8C0F0B3E1ACF43A300793B7D /* fixtures_m.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fixtures_m.h; sourceTree = "<group>"; };
8C0F0B3F1ACF43A300793B7D /* fixtures_m.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = fixtures_m.m; sourceTree = "<group>"; };
8C0F0B421ACF44E000793B7D /* fixtures_cpp.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fixtures_cpp.cpp; sourceTree = "<group>"; };
8C0F0B431ACF44E000793B7D /* fixtures_cpp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fixtures_cpp.h; sourceTree = "<group>"; };
8C0F0B461ACF44F200793B7D /* fixtures_mm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fixtures_mm.h; sourceTree = "<group>"; };
8C0F0B471ACF44F200793B7D /* fixtures_mm.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = fixtures_mm.mm; sourceTree = "<group>"; };
8C52AEF5195AAE32008A882A /* peekaview.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = peekaview.h; sourceTree = "<group>"; };
8C52AEF6195AAE32008A882A /* peekaview.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = peekaview.m; sourceTree = "<group>"; };
8C52AEF9195AAE70008A882A /* peekaviewTests💣.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "peekaviewTests💣.m"; sourceTree = "<group>"; };
8C9A202D195965F10013B6B3 /* libfixtures.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libfixtures.a; sourceTree = BUILT_PRODUCTS_DIR; };
8C9A2030195965F10013B6B3 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
8C9A2033195965F10013B6B3 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
8C9A2034195965F10013B6B3 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; };
8C9A2035195965F10013B6B3 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
8C9A2038195965F10013B6B3 /* fixtures-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "fixtures-Prefix.pch"; sourceTree = "<group>"; };
8C9A2039195965F10013B6B3 /* fixtures.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = fixtures.h; sourceTree = "<group>"; };
8C9A203A195965F10013B6B3 /* fixtures.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = fixtures.m; sourceTree = "<group>"; };
8C9A2040195965F10013B6B3 /* fixturesTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = fixturesTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
8C9A2049195965F10013B6B3 /* fixturesTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "fixturesTests-Info.plist"; sourceTree = "<group>"; };
8C9A204B195965F10013B6B3 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
8C9A204D195965F10013B6B3 /* fixturesTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = fixturesTests.m; sourceTree = "<group>"; };
B1E6980225F96B670086A3E2 /* FixtureFramework.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = FixtureFramework.framework; sourceTree = BUILT_PRODUCTS_DIR; };
B1E6980425F96B670086A3E2 /* FixtureFramework.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FixtureFramework.h; sourceTree = "<group>"; };
B1E6980525F96B670086A3E2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
B1E6980F25F96B680086A3E2 /* FixtureFrameworkTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FixtureFrameworkTests.swift; sourceTree = "<group>"; };
B1E6981125F96B680086A3E2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
B1E6981F25F96B930086A3E2 /* FlashExperiment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FlashExperiment.swift; sourceTree = "<group>"; };
B1E6982725F96BD30086A3E2 /* FlashExperimentTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FlashExperimentTests.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
377330761CC42A58005EAF65 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
85AE69031E45F0F900DA2D47 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
85AE69041E45F0F900DA2D47 /* libfixtures.a in Frameworks */,
85AE69051E45F0F900DA2D47 /* libfixturesTwo.dylib in Frameworks */,
85AE69061E45F0F900DA2D47 /* Cocoa.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
8C9A202A195965F10013B6B3 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
8C9A2031195965F10013B6B3 /* Cocoa.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
8C9A203D195965F10013B6B3 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
8C9A2046195965F10013B6B3 /* libfixtures.a in Frameworks */,
377330821CC42ABF005EAF65 /* libfixturesTwo.dylib in Frameworks */,
8C9A2043195965F10013B6B3 /* Cocoa.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
B1E697FF25F96B670086A3E2 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
3773307A1CC42A58005EAF65 /* fixturesTwo */ = {
isa = PBXGroup;
children = (
3773307B1CC42A58005EAF65 /* fixturesTwo.h */,
3773307D1CC42A58005EAF65 /* fixturesTwo.m */,
);
path = fixturesTwo;
sourceTree = "<group>";
};
8C52AEF4195AAE16008A882A /* more_files */ = {
isa = PBXGroup;
children = (
8C52AEF5195AAE32008A882A /* peekaview.h */,
8C52AEF6195AAE32008A882A /* peekaview.m */,
155BBCA319E9CB6700BACB13 /* Branches.h */,
155BBCA419E9CB6700BACB13 /* Branches.m */,
155D8AFC19FED984004666BA /* Empty.h */,
155D8AFD19FED984004666BA /* Empty.m */,
);
path = more_files;
sourceTree = "<group>";
};
8C9A2024195965F00013B6B3 = {
isa = PBXGroup;
children = (
8C9A2036195965F10013B6B3 /* fixtures */,
3773307A1CC42A58005EAF65 /* fixturesTwo */,
8C9A2047195965F10013B6B3 /* fixturesTests */,
B1E6980325F96B670086A3E2 /* FixtureFramework */,
B1E6980E25F96B670086A3E2 /* FixtureFrameworkTests */,
8C9A202F195965F10013B6B3 /* Frameworks */,
8C9A202E195965F10013B6B3 /* Products */,
);
sourceTree = "<group>";
};
8C9A202E195965F10013B6B3 /* Products */ = {
isa = PBXGroup;
children = (
8C9A202D195965F10013B6B3 /* libfixtures.a */,
8C9A2040195965F10013B6B3 /* fixturesTests.xctest */,
377330791CC42A58005EAF65 /* libfixturesTwo.dylib */,
85AE690C1E45F0F900DA2D47 /* fixturesTestsSecond.xctest */,
B1E6980225F96B670086A3E2 /* FixtureFramework.framework */,
);
name = Products;
sourceTree = "<group>";
};
8C9A202F195965F10013B6B3 /* Frameworks */ = {
isa = PBXGroup;
children = (
8C9A2030195965F10013B6B3 /* Cocoa.framework */,
8C9A2032195965F10013B6B3 /* Other Frameworks */,
);
name = Frameworks;
sourceTree = "<group>";
};
8C9A2032195965F10013B6B3 /* Other Frameworks */ = {
isa = PBXGroup;
children = (
8C9A2033195965F10013B6B3 /* Foundation.framework */,
8C9A2034195965F10013B6B3 /* CoreData.framework */,
8C9A2035195965F10013B6B3 /* AppKit.framework */,
);
name = "Other Frameworks";
sourceTree = "<group>";
};
8C9A2036195965F10013B6B3 /* fixtures */ = {
isa = PBXGroup;
children = (
8C52AEF4195AAE16008A882A /* more_files */,
8C9A2039195965F10013B6B3 /* fixtures.h */,
8C9A203A195965F10013B6B3 /* fixtures.m */,
8C0F0B3E1ACF43A300793B7D /* fixtures_m.h */,
8C0F0B3F1ACF43A300793B7D /* fixtures_m.m */,
8C9A2037195965F10013B6B3 /* Supporting Files */,
8C0F0B421ACF44E000793B7D /* fixtures_cpp.cpp */,
8C0F0B431ACF44E000793B7D /* fixtures_cpp.h */,
8C0F0B461ACF44F200793B7D /* fixtures_mm.h */,
8C0F0B471ACF44F200793B7D /* fixtures_mm.mm */,
);
path = fixtures;
sourceTree = "<group>";
};
8C9A2037195965F10013B6B3 /* Supporting Files */ = {
isa = PBXGroup;
children = (
8C9A2038195965F10013B6B3 /* fixtures-Prefix.pch */,
);
path = "Supporting Files";
sourceTree = "<group>";
};
8C9A2047195965F10013B6B3 /* fixturesTests */ = {
isa = PBXGroup;
children = (
8C9A204D195965F10013B6B3 /* fixturesTests.m */,
8554482E1E461FAF0032518E /* fixturesTestsSecond.m */,
8C9A2048195965F10013B6B3 /* Supporting Files */,
8C52AEF9195AAE70008A882A /* peekaviewTests💣.m */,
155BBCA719E9CCC500BACB13 /* BranchesTests.m */,
);
path = fixturesTests;
sourceTree = "<group>";
};
8C9A2048195965F10013B6B3 /* Supporting Files */ = {
isa = PBXGroup;
children = (
8C9A2049195965F10013B6B3 /* fixturesTests-Info.plist */,
8C9A204A195965F10013B6B3 /* InfoPlist.strings */,
);
path = "Supporting Files";
sourceTree = "<group>";
};
B1E6980325F96B670086A3E2 /* FixtureFramework */ = {
isa = PBXGroup;
children = (
B1E6980425F96B670086A3E2 /* FixtureFramework.h */,
B1E6980525F96B670086A3E2 /* Info.plist */,
B1E6981F25F96B930086A3E2 /* FlashExperiment.swift */,
);
path = FixtureFramework;
sourceTree = "<group>";
};
B1E6980E25F96B670086A3E2 /* FixtureFrameworkTests */ = {
isa = PBXGroup;
children = (
B1E6980F25F96B680086A3E2 /* FixtureFrameworkTests.swift */,
B1E6981125F96B680086A3E2 /* Info.plist */,
B1E6982725F96BD30086A3E2 /* FlashExperimentTests.swift */,
);
path = FixtureFrameworkTests;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
377330771CC42A58005EAF65 /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
3773307C1CC42A58005EAF65 /* fixturesTwo.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
8C9A202B195965F10013B6B3 /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
8C0F0B481ACF44F200793B7D /* fixtures_mm.h in Headers */,
8C0F0B401ACF43A300793B7D /* fixtures_m.h in Headers */,
155D8AFE19FED984004666BA /* Empty.h in Headers */,
155BBCA519E9CB6700BACB13 /* Branches.h in Headers */,
8C0F0B451ACF44E000793B7D /* fixtures_cpp.h in Headers */,
8C52AEF7195AAE32008A882A /* peekaview.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
B1E697FD25F96B670086A3E2 /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
B1E6981225F96B680086A3E2 /* FixtureFramework.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
377330781CC42A58005EAF65 /* fixturesTwo */ = {
isa = PBXNativeTarget;
buildConfigurationList = 3773307F1CC42A58005EAF65 /* Build configuration list for PBXNativeTarget "fixturesTwo" */;
buildPhases = (
377330751CC42A58005EAF65 /* Sources */,
377330761CC42A58005EAF65 /* Frameworks */,
377330771CC42A58005EAF65 /* Headers */,
);
buildRules = (
);
dependencies = (
);
name = fixturesTwo;
productName = fixturesTwo;
productReference = 377330791CC42A58005EAF65 /* libfixturesTwo.dylib */;
productType = "com.apple.product-type.library.dynamic";
};
85AE68FC1E45F0F900DA2D47 /* fixturesTestsSecond */ = {
isa = PBXNativeTarget;
buildConfigurationList = 85AE69091E45F0F900DA2D47 /* Build configuration list for PBXNativeTarget "fixturesTestsSecond" */;
buildPhases = (
85AE68FF1E45F0F900DA2D47 /* Sources */,
85AE69031E45F0F900DA2D47 /* Frameworks */,
85AE69071E45F0F900DA2D47 /* Resources */,
);
buildRules = (
);
dependencies = (
85AE68FD1E45F0F900DA2D47 /* PBXTargetDependency */,
);
name = fixturesTestsSecond;
productName = fixturesTests;
productReference = 85AE690C1E45F0F900DA2D47 /* fixturesTestsSecond.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
8C9A202C195965F10013B6B3 /* fixtures */ = {
isa = PBXNativeTarget;
buildConfigurationList = 8C9A2051195965F10013B6B3 /* Build configuration list for PBXNativeTarget "fixtures" */;
buildPhases = (
8C9A2029195965F10013B6B3 /* Sources */,
8C9A202A195965F10013B6B3 /* Frameworks */,
8C9A202B195965F10013B6B3 /* Headers */,
);
buildRules = (
);
dependencies = (
B1E6983025F96F490086A3E2 /* PBXTargetDependency */,
);
name = fixtures;
productName = fixtures;
productReference = 8C9A202D195965F10013B6B3 /* libfixtures.a */;
productType = "com.apple.product-type.library.static";
};
8C9A203F195965F10013B6B3 /* fixturesTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 8C9A2054195965F10013B6B3 /* Build configuration list for PBXNativeTarget "fixturesTests" */;
buildPhases = (
8C9A203C195965F10013B6B3 /* Sources */,
8C9A203D195965F10013B6B3 /* Frameworks */,
8C9A203E195965F10013B6B3 /* Resources */,
);
buildRules = (
);
dependencies = (
B1E6983825F970320086A3E2 /* PBXTargetDependency */,
8C9A2045195965F10013B6B3 /* PBXTargetDependency */,
);
name = fixturesTests;
productName = fixturesTests;
productReference = 8C9A2040195965F10013B6B3 /* fixturesTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
B1E6980125F96B670086A3E2 /* FixtureFramework */ = {
isa = PBXNativeTarget;
buildConfigurationList = B1E6981725F96B680086A3E2 /* Build configuration list for PBXNativeTarget "FixtureFramework" */;
buildPhases = (
B1E697FD25F96B670086A3E2 /* Headers */,
B1E697FE25F96B670086A3E2 /* Sources */,
B1E697FF25F96B670086A3E2 /* Frameworks */,
B1E6980025F96B670086A3E2 /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = FixtureFramework;
productName = FixtureFramework;
productReference = B1E6980225F96B670086A3E2 /* FixtureFramework.framework */;
productType = "com.apple.product-type.framework";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
8C9A2025195965F00013B6B3 /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 1240;
LastUpgradeCheck = 0510;
ORGANIZATIONNAME = marklarr;
TargetAttributes = {
377330781CC42A58005EAF65 = {
CreatedOnToolsVersion = 7.3;
};
B1E6980125F96B670086A3E2 = {
CreatedOnToolsVersion = 12.4;
LastSwiftMigration = 1240;
ProvisioningStyle = Automatic;
};
};
};
buildConfigurationList = 8C9A2028195965F00013B6B3 /* Build configuration list for PBXProject "fixtures" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
English,
en,
);
mainGroup = 8C9A2024195965F00013B6B3;
productRefGroup = 8C9A202E195965F10013B6B3 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
8C9A202C195965F10013B6B3 /* fixtures */,
377330781CC42A58005EAF65 /* fixturesTwo */,
8C9A203F195965F10013B6B3 /* fixturesTests */,
85AE68FC1E45F0F900DA2D47 /* fixturesTestsSecond */,
B1E6980125F96B670086A3E2 /* FixtureFramework */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
85AE69071E45F0F900DA2D47 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
85AE69081E45F0F900DA2D47 /* InfoPlist.strings in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
8C9A203E195965F10013B6B3 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
8C9A204C195965F10013B6B3 /* InfoPlist.strings in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
B1E6980025F96B670086A3E2 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
377330751CC42A58005EAF65 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
3773307E1CC42A58005EAF65 /* fixturesTwo.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
85AE68FF1E45F0F900DA2D47 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
8554482F1E461FAF0032518E /* fixturesTestsSecond.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
8C9A2029195965F10013B6B3 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
8C9A203B195965F10013B6B3 /* fixtures.m in Sources */,
155D8AFF19FED984004666BA /* Empty.m in Sources */,
8C0F0B411ACF43A300793B7D /* fixtures_m.m in Sources */,
8C0F0B441ACF44E000793B7D /* fixtures_cpp.cpp in Sources */,
155BBCA619E9CB6700BACB13 /* Branches.m in Sources */,
8C0F0B491ACF44F200793B7D /* fixtures_mm.mm in Sources */,
8C52AEF8195AAE33008A882A /* peekaview.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
8C9A203C195965F10013B6B3 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
8C9A204E195965F10013B6B3 /* fixturesTests.m in Sources */,
8C52AEFA195AAE70008A882A /* peekaviewTests💣.m in Sources */,
155BBCA819E9CCC500BACB13 /* BranchesTests.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
B1E697FE25F96B670086A3E2 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
B1E6982025F96B930086A3E2 /* FlashExperiment.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
85AE68FD1E45F0F900DA2D47 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 8C9A202C195965F10013B6B3 /* fixtures */;
targetProxy = 85AE68FE1E45F0F900DA2D47 /* PBXContainerItemProxy */;
};
8C9A2045195965F10013B6B3 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 8C9A202C195965F10013B6B3 /* fixtures */;
targetProxy = 8C9A2044195965F10013B6B3 /* PBXContainerItemProxy */;
};
B1E6983025F96F490086A3E2 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = B1E6980125F96B670086A3E2 /* FixtureFramework */;
targetProxy = B1E6982F25F96F490086A3E2 /* PBXContainerItemProxy */;
};
B1E6983825F970320086A3E2 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = B1E6980125F96B670086A3E2 /* FixtureFramework */;
targetProxy = B1E6983725F970320086A3E2 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
8C9A204A195965F10013B6B3 /* InfoPlist.strings */ = {
isa = PBXVariantGroup;
children = (
8C9A204B195965F10013B6B3 /* en */,
);
name = InfoPlist.strings;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
377330801CC42A58005EAF65 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ANALYZER_NONNULL = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
EXECUTABLE_PREFIX = lib;
GCC_NO_COMMON_BLOCKS = YES;
MTL_ENABLE_DEBUG_INFO = YES;
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
};
377330811CC42A58005EAF65 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ANALYZER_NONNULL = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
COPY_PHASE_STRIP = NO;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
ENABLE_STRICT_OBJC_MSGSEND = YES;
EXECUTABLE_PREFIX = lib;
GCC_NO_COMMON_BLOCKS = YES;
MTL_ENABLE_DEBUG_INFO = NO;
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
};
85AE690A1E45F0F900DA2D47 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
COMBINE_HIDPI_IMAGES = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(DEVELOPER_FRAMEWORKS_DIR)",
"$(inherited)",
);
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "fixtures/Supporting Files/fixtures-Prefix.pch";
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = xctest;
};
name = Debug;
};
85AE690B1E45F0F900DA2D47 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
COMBINE_HIDPI_IMAGES = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(DEVELOPER_FRAMEWORKS_DIR)",
"$(inherited)",
);
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "fixtures/Supporting Files/fixtures-Prefix.pch";
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = xctest;
};
name = Release;
};
8C9A204F195965F10013B6B3 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_GENERATE_TEST_COVERAGE_FILES = YES;
GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.9;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
};
name = Debug;
};
8C9A2050195965F10013B6B3 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_GENERATE_TEST_COVERAGE_FILES = YES;
GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.9;
SDKROOT = macosx;
};
name = Release;
};
8C9A2052195965F10013B6B3 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
GCC_GENERATE_TEST_COVERAGE_FILES = YES;
GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = YES;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "fixtures/Supporting Files/fixtures-Prefix.pch";
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
};
8C9A2053195965F10013B6B3 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
GCC_GENERATE_TEST_COVERAGE_FILES = YES;
GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = YES;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "fixtures/Supporting Files/fixtures-Prefix.pch";
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
};
8C9A2055195965F10013B6B3 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
COMBINE_HIDPI_IMAGES = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(DEVELOPER_FRAMEWORKS_DIR)",
"$(inherited)",
);
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "fixtures/Supporting Files/fixtures-Prefix.pch";
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
INFOPLIST_FILE = "fixturesTests/Supporting Files/fixturesTests-Info.plist";
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = xctest;
};
name = Debug;
};
8C9A2056195965F10013B6B3 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
COMBINE_HIDPI_IMAGES = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(DEVELOPER_FRAMEWORKS_DIR)",
"$(inherited)",
);
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "fixtures/Supporting Files/fixtures-Prefix.pch";
INFOPLIST_FILE = "fixturesTests/Supporting Files/fixturesTests-Info.plist";
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = xctest;
};
name = Release;
};
B1E6981325F96B680086A3E2 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_NO_COMMON_BLOCKS = YES;
INFOPLIST_FILE = FixtureFramework/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
MACOSX_DEPLOYMENT_TARGET = 11.1;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.onato.FixtureFramework;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SKIP_INSTALL = YES;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Debug;
};
B1E6981425F96B680086A3E2 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_NO_COMMON_BLOCKS = YES;
INFOPLIST_FILE = FixtureFramework/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
MACOSX_DEPLOYMENT_TARGET = 11.1;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.onato.FixtureFramework;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SKIP_INSTALL = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
3773307F1CC42A58005EAF65 /* Build configuration list for PBXNativeTarget "fixturesTwo" */ = {
isa = XCConfigurationList;
buildConfigurations = (
377330801CC42A58005EAF65 /* Debug */,
377330811CC42A58005EAF65 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
85AE69091E45F0F900DA2D47 /* Build configuration list for PBXNativeTarget "fixturesTestsSecond" */ = {
isa = XCConfigurationList;
buildConfigurations = (
85AE690A1E45F0F900DA2D47 /* Debug */,
85AE690B1E45F0F900DA2D47 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
8C9A2028195965F00013B6B3 /* Build configuration list for PBXProject "fixtures" */ = {
isa = XCConfigurationList;
buildConfigurations = (
8C9A204F195965F10013B6B3 /* Debug */,
8C9A2050195965F10013B6B3 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
8C9A2051195965F10013B6B3 /* Build configuration list for PBXNativeTarget "fixtures" */ = {
isa = XCConfigurationList;
buildConfigurations = (
8C9A2052195965F10013B6B3 /* Debug */,
8C9A2053195965F10013B6B3 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
8C9A2054195965F10013B6B3 /* Build configuration list for PBXNativeTarget "fixturesTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
8C9A2055195965F10013B6B3 /* Debug */,
8C9A2056195965F10013B6B3 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
B1E6981725F96B680086A3E2 /* Build configuration list for PBXNativeTarget "FixtureFramework" */ = {
isa = XCConfigurationList;
buildConfigurations = (
B1E6981325F96B680086A3E2 /* Debug */,
B1E6981425F96B680086A3E2 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 8C9A2025195965F00013B6B3 /* Project object */;
}
================================================
FILE: spec/fixtures/fixtures.xcodeproj/project.xcworkspace/contents.xcworkspacedata
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:fixtures.xcodeproj">
</FileRef>
</Workspace>
================================================
FILE: spec/fixtures/fixtures.xcodeproj/xcshareddata/xcschemes/aggregateFixturesTests.xcscheme
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0730"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "85AE68FC1E45F0F900DA2D47"
BuildableName = "fixturesTestsSecond.xctest"
BlueprintName = "fixturesTestsSecond"
ReferencedContainer = "container:fixtures.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "85AE68FC1E45F0F900DA2D47"
BuildableName = "fixturesTestsSecond.xctest"
BlueprintName = "fixturesTestsSecond"
ReferencedContainer = "container:fixtures.xcodeproj">
</BuildableReference>
</TestableReference>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "8C9A203F195965F10013B6B3"
BuildableName = "fixturesTests.xctest"
BlueprintName = "fixturesTests"
ReferencedContainer = "container:fixtures.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "85AE68FC1E45F0F900DA2D47"
BuildableName = "fixturesTestsSecond.xctest"
BlueprintName = "fixturesTestsSecond"
ReferencedContainer = "container:fixtures.xcodeproj">
</BuildableReference>
</Macro
gitextract_cr8xe6x0/
├── .coveralls.yml
├── .gitignore
├── .travis.yml
├── CHANGELOG.md
├── Gemfile
├── LICENSE.txt
├── README.md
├── Rakefile
├── assets/
│ ├── highlight.pack.js
│ └── slather.css
├── bin/
│ └── slather
├── lib/
│ ├── cocoapods_plugin.rb
│ ├── slather/
│ │ ├── command/
│ │ │ ├── coverage_command.rb
│ │ │ ├── setup_command.rb
│ │ │ └── version_command.rb
│ │ ├── coverage_file.rb
│ │ ├── coverage_info.rb
│ │ ├── coverage_service/
│ │ │ ├── cobertura_xml_output.rb
│ │ │ ├── coveralls.rb
│ │ │ ├── gutter_json_output.rb
│ │ │ ├── hardcover.rb
│ │ │ ├── html_output.rb
│ │ │ ├── json_output.rb
│ │ │ ├── llvm_cov_output.rb
│ │ │ ├── simple_output.rb
│ │ │ └── sonarqube_xml_output.rb
│ │ ├── coveralls_coverage.rb
│ │ ├── profdata_coverage_file.rb
│ │ ├── project.rb
│ │ └── version.rb
│ └── slather.rb
├── slather.gemspec
└── spec/
├── fixtures/
│ ├── FixtureFramework/
│ │ ├── FixtureFramework.h
│ │ ├── FlashExperiment.swift
│ │ └── Info.plist
│ ├── FixtureFrameworkTests/
│ │ ├── FixtureFrameworkTests.swift
│ │ ├── FlashExperimentTests.swift
│ │ └── Info.plist
│ ├── fixtures/
│ │ ├── Fixtures.swift
│ │ ├── Supporting Files/
│ │ │ └── fixtures-Prefix.pch
│ │ ├── fixtures.h
│ │ ├── fixtures.m
│ │ ├── fixtures_cpp.cpp
│ │ ├── fixtures_cpp.h
│ │ ├── fixtures_m.h
│ │ ├── fixtures_m.m
│ │ ├── fixtures_mm.h
│ │ ├── fixtures_mm.mm
│ │ ├── more_files/
│ │ │ ├── Branches.h
│ │ │ ├── Branches.m
│ │ │ ├── Empty.h
│ │ │ ├── Empty.m
│ │ │ ├── peekaview.h
│ │ │ └── peekaview.m
│ │ └── other_fixtures.m
│ ├── fixtures.xcodeproj/
│ │ ├── project.pbxproj
│ │ ├── project.xcworkspace/
│ │ │ └── contents.xcworkspacedata
│ │ └── xcshareddata/
│ │ └── xcschemes/
│ │ ├── aggregateFixturesTests.xcscheme
│ │ ├── fixtures.xcscheme
│ │ ├── fixturesTests.xcscheme
│ │ ├── fixturesTestsSecond.xcscheme
│ │ └── fixturesTwo.xcscheme
│ ├── fixtures.xcworkspace/
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata/
│ │ ├── IDEWorkspaceChecks.plist
│ │ └── xcschemes/
│ │ └── fixturesTestsWorkspace.xcscheme
│ ├── fixturesTests/
│ │ ├── BranchesTests.m
│ │ ├── Supporting Files/
│ │ │ ├── en.lproj/
│ │ │ │ └── InfoPlist.strings
│ │ │ └── fixturesTests-Info.plist
│ │ ├── fixturesTests.m
│ │ ├── fixturesTestsSecond.m
│ │ └── peekaviewTests💣.m
│ ├── fixturesTwo/
│ │ ├── fixturesTwo.h
│ │ └── fixturesTwo.m
│ ├── fixtures_html/
│ │ ├── Branches.m.html
│ │ ├── BranchesTests.m.html
│ │ ├── fixtures.m.html
│ │ ├── fixturesTests.m.html
│ │ ├── index.html
│ │ └── peekaviewTests💣.m.html
│ ├── gutter.json
│ └── sonarqube-generic-coverage.xml
├── slather/
│ ├── cocoapods_plugin_spec.rb
│ ├── coverage_file_spec.rb
│ ├── coverage_service/
│ │ ├── cobertura_xml_spec.rb
│ │ ├── coveralls_spec.rb
│ │ ├── gutter_json_spec.rb
│ │ ├── hardcover_spec.rb
│ │ ├── html_output_spec.rb
│ │ ├── json_spec.rb
│ │ ├── llvm_cov_spec.rb
│ │ ├── simple_output_spec.rb
│ │ └── sonarqube_xml_spec.rb
│ ├── profdata_coverage_spec.rb
│ └── project_spec.rb
└── spec_helper.rb
SYMBOL INDEX (284 symbols across 23 files)
FILE: assets/highlight.pack.js
function n (line 1) | function n(e){return e.replace(/&/gm,"&").replace(/</gm,"<").repl...
function t (line 1) | function t(e){return e.nodeName.toLowerCase()}
function r (line 1) | function r(e,n){var t=e&&e.exec(n);return t&&0==t.index}
function a (line 1) | function a(e){return/no-?highlight|plain|text/.test(e)}
function i (line 1) | function i(e){var n,t,r,i=e.className+" ";if(i+=e.parentNode?e.parentNod...
function o (line 1) | function o(e,n){var t,r={};for(t in e)r[t]=e[t];if(n)for(t in n)r[t]=n[t...
function u (line 1) | function u(e){var n=[];return function r(e,a){for(var i=e.firstChild;i;i...
function c (line 1) | function c(e,r,a){function i(){return e.length&&r.length?e[0].offset!=r[...
function s (line 1) | function s(e){function n(e){return e&&e.source||e}function t(t,r){return...
function f (line 1) | function f(e,t,a,i){function o(e,n){for(var t=0;t<n.c.length;t++)if(r(n....
function l (line 1) | function l(e,t){t=t||w.languages||Object.keys(x);var r={r:0,value:n(e)},...
function g (line 1) | function g(e){return w.tabReplace&&(e=e.replace(/^((<[^>]+>|\t)+)/gm,fun...
function h (line 1) | function h(e,n,t){var r=n?R[n]:t,a=[e.trim()];return e.match(/\bhljs\b/)...
function p (line 1) | function p(e){var n=i(e);if(!a(n)){var t;w.useBR?(t=document.createEleme...
function d (line 1) | function d(e){w=o(w,e)}
function b (line 1) | function b(){if(!b.called){b.called=!0;var e=document.querySelectorAll("...
function v (line 1) | function v(){addEventListener("DOMContentLoaded",b,!1),addEventListener(...
function m (line 1) | function m(n,t){var r=x[n]=t(e);r.aliases&&r.aliases.forEach(function(e)...
function N (line 1) | function N(){return Object.keys(x)}
function E (line 1) | function E(e){return x[e]||x[R[e]]}
FILE: lib/slather.rb
type Slather (line 18) | module Slather
function prepare_pods (line 22) | def self.prepare_pods(pods)
function xcode_version (line 26) | def self.xcode_version
FILE: lib/slather/command/coverage_command.rb
class CoverageCommand (line 1) | class CoverageCommand < Clamp::Command
method execute (line 41) | def execute
method setup_ymlfile (line 69) | def setup_ymlfile
method setup_build_directory (line 73) | def setup_build_directory
method setup_source_directory (line 77) | def setup_source_directory
method setup_output_directory (line 81) | def setup_output_directory
method setup_ignore_list (line 85) | def setup_ignore_list
method setup_service_name (line 89) | def setup_service_name
method post (line 107) | def post
method project (line 111) | def project
method setup_coverage_service (line 122) | def setup_coverage_service
method setup_verbose_mode (line 144) | def setup_verbose_mode
method setup_input_format (line 148) | def setup_input_format
method setup_scheme (line 152) | def setup_scheme
method setup_configuration (line 156) | def setup_configuration
method setup_workspace (line 160) | def setup_workspace
method setup_binary_file (line 164) | def setup_binary_file
method setup_binary_basename (line 168) | def setup_binary_basename
method setup_arch (line 172) | def setup_arch
method setup_source_files (line 176) | def setup_source_files
method setup_decimals (line 180) | def setup_decimals
FILE: lib/slather/command/setup_command.rb
class SetupCommand (line 1) | class SetupCommand < Clamp::Command
method execute (line 7) | def execute
method setup_ymlfile (line 18) | def setup_ymlfile
FILE: lib/slather/command/version_command.rb
class VersionCommand (line 1) | class VersionCommand < Clamp::Command
method execute (line 3) | def execute
FILE: lib/slather/coverage_file.rb
type Slather (line 4) | module Slather
class CoverageFile (line 5) | class CoverageFile
method initialize (line 12) | def initialize(project, gcno_file_pathname)
method source_file_pathname (line 17) | def source_file_pathname
method source_file (line 36) | def source_file
method source_data (line 40) | def source_data
method gcov_data (line 44) | def gcov_data
method all_lines (line 67) | def all_lines
method cleaned_gcov_data (line 76) | def cleaned_gcov_data
method raw_data (line 81) | def raw_data
method line_coverage_data (line 85) | def line_coverage_data
method line_number_in_line (line 97) | def line_number_in_line(line)
method coverage_for_line (line 101) | def coverage_for_line(line)
method branch_coverage_data (line 115) | def branch_coverage_data
method source_file_basename (line 134) | def source_file_basename
method line_number_separator (line 138) | def line_number_separator
method supported_file_extensions (line 142) | def supported_file_extensions
FILE: lib/slather/coverage_info.rb
type Slather (line 1) | module Slather
type CoverageInfo (line 2) | module CoverageInfo
function num_lines_tested (line 4) | def num_lines_tested
function num_lines_testable (line 8) | def num_lines_testable
function rate_lines_tested (line 12) | def rate_lines_tested
function percentage_lines_tested (line 20) | def percentage_lines_tested
function branch_coverage_data_for_statement_on_line (line 28) | def branch_coverage_data_for_statement_on_line(line_number)
function num_branches_for_statement_on_line (line 32) | def num_branches_for_statement_on_line(line_number)
function num_branch_hits_for_statement_on_line (line 36) | def num_branch_hits_for_statement_on_line(line_number)
function rate_branch_coverage_for_statement_on_line (line 40) | def rate_branch_coverage_for_statement_on_line(line_number)
function percentage_branch_coverage_for_statement_on_line (line 49) | def percentage_branch_coverage_for_statement_on_line(line_number)
function num_branches_testable (line 53) | def num_branches_testable
function num_branches_tested (line 59) | def num_branches_tested
function rate_branches_tested (line 65) | def rate_branches_tested
function source_file_pathname_relative_to_repo_root (line 73) | def source_file_pathname_relative_to_repo_root
function ignored? (line 77) | def ignored?
function include_file? (line 83) | def include_file?
FILE: lib/slather/coverage_service/cobertura_xml_output.rb
type Slather (line 4) | module Slather
type CoverageService (line 5) | module CoverageService
type CoberturaXmlOutput (line 6) | module CoberturaXmlOutput
function coverage_file_class (line 8) | def coverage_file_class
function post (line 17) | def post
function store_report (line 22) | def store_report(report)
function grouped_coverage_files (line 31) | def grouped_coverage_files(coverage_files)
function create_xml_report (line 44) | def create_xml_report(coverage_files)
function create_class_node (line 120) | def create_class_node(coverage_file)
function create_line_node (line 145) | def create_line_node(line, coverage_file)
function create_empty_xml_report (line 169) | def create_empty_xml_report
FILE: lib/slather/coverage_service/coveralls.rb
type Slather (line 1) | module Slather
type CoverageService (line 2) | module CoverageService
type Coveralls (line 3) | module Coveralls
function coverage_file_class (line 5) | def coverage_file_class
function travis_job_id (line 14) | def travis_job_id
function circleci_job_id (line 19) | def circleci_job_id
function circleci_pull_request (line 24) | def circleci_pull_request
function teamcity_job_id (line 29) | def teamcity_job_id
function jenkins_job_id (line 34) | def jenkins_job_id
function github_job_id (line 39) | def github_job_id
function bitrise_job_id (line 44) | def bitrise_job_id
function bitrise_pull_request (line 49) | def bitrise_pull_request
function github_pull_request (line 54) | def github_pull_request
function github_repo_name (line 59) | def github_repo_name
function jenkins_branch_name (line 64) | def jenkins_branch_name
function teamcity_branch_name (line 74) | def teamcity_branch_name
function github_branch_name (line 79) | def github_branch_name
function bitrise_branch_name (line 84) | def bitrise_branch_name
function buildkite_job_id (line 89) | def buildkite_job_id
function buildkite_pull_request (line 94) | def buildkite_pull_request
function jenkins_git_info (line 99) | def jenkins_git_info
function teamcity_git_info (line 111) | def teamcity_git_info
function circleci_build_url (line 124) | def circleci_build_url
function circleci_git_info (line 129) | def circleci_git_info
function buildkite_git_info (line 141) | def buildkite_git_info
function buildkite_build_url (line 153) | def buildkite_build_url
function github_git_info (line 157) | def github_git_info
function bitrise_git_info (line 169) | def bitrise_git_info
function github_build_url (line 182) | def github_build_url
function is_parallel (line 187) | def is_parallel
function github_job_name (line 192) | def github_job_name
function coveralls_coverage_data (line 197) | def coveralls_coverage_data
function post (line 339) | def post
function coveralls_api_jobs_path (line 363) | def coveralls_api_jobs_path
FILE: lib/slather/coverage_service/gutter_json_output.rb
type Slather (line 1) | module Slather
type CoverageService (line 2) | module CoverageService
type GutterJsonOutput (line 3) | module GutterJsonOutput
function coverage_file_class (line 5) | def coverage_file_class
function post (line 14) | def post
FILE: lib/slather/coverage_service/hardcover.rb
type Slather (line 1) | module Slather
type CoverageService (line 2) | module CoverageService
type Hardcover (line 3) | module Hardcover
function coverage_file_class (line 5) | def coverage_file_class
function jenkins_job_id (line 14) | def jenkins_job_id
function hardcover_coverage_data (line 19) | def hardcover_coverage_data
function post (line 37) | def post
function hardcover_api_jobs_path (line 50) | def hardcover_api_jobs_path
function hardcover_base_url (line 55) | def hardcover_base_url
FILE: lib/slather/coverage_service/html_output.rb
type Slather (line 4) | module Slather
type CoverageService (line 5) | module CoverageService
type HtmlOutput (line 6) | module HtmlOutput
function coverage_file_class (line 10) | def coverage_file_class
function directory_path (line 19) | def directory_path
function post (line 25) | def post
function print_path_coverage (line 37) | def print_path_coverage(index_html)
function open_coverage (line 42) | def open_coverage(index_html)
function create_html_reports (line 47) | def create_html_reports(coverage_files)
function generate_reports (line 52) | def generate_reports(reports)
function create_index_html (line 67) | def create_index_html(coverage_files)
function create_htmls_from_files (line 149) | def create_htmls_from_files(coverage_files)
function create_html_from_file (line 153) | def create_html_from_file(coverage_file)
function generate_html_template (line 235) | def generate_html_template(title, is_index, is_file_empty)
function gem_root_path (line 283) | def gem_root_path
function class_for_coverage_line (line 287) | def class_for_coverage_line(coverage_file, coverage_line)
function hits_for_coverage_line (line 296) | def hits_for_coverage_line(coverage_file, coverage_line)
function class_for_coverage_percentage (line 305) | def class_for_coverage_percentage(percentage)
FILE: lib/slather/coverage_service/json_output.rb
type Slather (line 4) | module Slather
type CoverageService (line 5) | module CoverageService
type JsonOutput (line 6) | module JsonOutput
function coverage_file_class (line 8) | def coverage_file_class
function post (line 17) | def post
function store_report (line 28) | def store_report(report)
FILE: lib/slather/coverage_service/llvm_cov_output.rb
type Slather (line 4) | module Slather
type CoverageService (line 5) | module CoverageService
type LlvmCovOutput (line 6) | module LlvmCovOutput
function coverage_file_class (line 8) | def coverage_file_class
function post (line 17) | def post
function store_report (line 25) | def store_report(report)
FILE: lib/slather/coverage_service/simple_output.rb
type Slather (line 1) | module Slather
type CoverageService (line 2) | module CoverageService
type SimpleOutput (line 3) | module SimpleOutput
function coverage_file_class (line 5) | def coverage_file_class
function post (line 14) | def post
FILE: lib/slather/coverage_service/sonarqube_xml_output.rb
type Slather (line 4) | module Slather
type CoverageService (line 5) | module CoverageService
type SonarqubeXmlOutput (line 6) | module SonarqubeXmlOutput
function coverage_file_class (line 8) | def coverage_file_class
function post (line 17) | def post
function store_report (line 22) | def store_report(report)
function create_xml_report (line 31) | def create_xml_report(coverage_files)
function create_empty_xml_report (line 52) | def create_empty_xml_report
FILE: lib/slather/coveralls_coverage.rb
type Slather (line 1) | module Slather
type CoverallsCoverage (line 2) | module CoverallsCoverage
function as_json (line 4) | def as_json
FILE: lib/slather/profdata_coverage_file.rb
type Slather (line 5) | module Slather
class ProfdataCoverageFile (line 6) | class ProfdataCoverageFile
method initialize (line 13) | def initialize(project, source, line_numbers_first)
method create_line_data (line 20) | def create_line_data
method path_on_first_line? (line 27) | def path_on_first_line?
method source_file_pathname (line 31) | def source_file_pathname
method source_file_pathname= (line 63) | def source_file_pathname= (source_file_pathname)
method source_file (line 67) | def source_file
method source_code_lines (line 71) | def source_code_lines
method ignore_error_lines (line 76) | def ignore_error_lines(lines, line_numbers_first = self.line_numbers...
method source_data (line 84) | def source_data
method all_lines (line 88) | def all_lines
method raw_source (line 92) | def raw_source
method cleaned_gcov_data (line 98) | def cleaned_gcov_data
method raw_data (line 102) | def raw_data
method line_number_in_line (line 106) | def line_number_in_line(line, line_numbers_first = self.line_numbers...
method line_coverage_data (line 139) | def line_coverage_data
method coverage_for_line (line 145) | def coverage_for_line(line, line_numbers_first = self.line_numbers_f...
method branch_coverage_data (line 189) | def branch_coverage_data
method branch_region_data (line 207) | def branch_region_data
method source_file_basename (line 235) | def source_file_basename
method line_number_separator (line 239) | def line_number_separator
method supported_file_extensions (line 243) | def supported_file_extensions
method ignored? (line 248) | def ignored?
FILE: lib/slather/project.rb
type Xcodeproj (line 7) | module Xcodeproj
class Project (line 9) | class Project
method slather_setup_for_coverage (line 11) | def slather_setup_for_coverage(format = :auto)
type Slather (line 43) | module Slather
class Project (line 44) | class Project < Xcodeproj::Project
method open (line 52) | def self.open(xcodeproj)
method failure_help_string (line 58) | def failure_help_string
method derived_data_path (line 62) | def derived_data_path
method coverage_files (line 96) | def coverage_files
method gcov_coverage_files (line 104) | def gcov_coverage_files
method profdata_coverage_files (line 119) | def profdata_coverage_files
method pathnames_per_binary (line 137) | def pathnames_per_binary(binary_path)
method create_coverage_files_for_binary (line 156) | def create_coverage_files_for_binary(binary_path, pathnames_per_binary)
method create_coverage_files (line 179) | def create_coverage_files(binary_path, path_objects)
method create_profdata (line 202) | def create_profdata(binary_path, pathnames)
method remove_extension (line 207) | def remove_extension(path)
method first_product_name (line 211) | def first_product_name
method profdata_coverage_dir (line 218) | def profdata_coverage_dir
method profdata_file (line 253) | def profdata_file
method unsafe_llvm_cov_export_output (line 267) | def unsafe_llvm_cov_export_output(binary_path)
method llvm_cov_export_output (line 285) | def llvm_cov_export_output(binary_path)
method unsafe_profdata_llvm_cov_output (line 291) | def unsafe_profdata_llvm_cov_output(binary_path, source_files)
method profdata_llvm_cov_output (line 312) | def profdata_llvm_cov_output(binary_path, source_files)
method dedupe (line 318) | def dedupe(coverage_files)
method yml_filename= (line 325) | def self.yml_filename=(var)
method yml_filename (line 329) | def self.yml_filename
method yml (line 333) | def self.yml
method configure (line 337) | def configure
method configure_build_directory (line 377) | def configure_build_directory
method configure_source_directory (line 381) | def configure_source_directory
method configure_output_directory (line 385) | def configure_output_directory
method configure_ignore_list (line 389) | def configure_ignore_list
method configure_source_files (line 393) | def configure_source_files
method configure_ci_service (line 397) | def configure_ci_service
method configure_input_format (line 401) | def configure_input_format
method input_format= (line 405) | def input_format=(format)
method configure_scheme (line 417) | def configure_scheme
method configure_configuration (line 421) | def configure_configuration
method configure_decimals (line 425) | def configure_decimals
method configure_workspace (line 431) | def configure_workspace
method ci_service= (line 435) | def ci_service=(service)
method configure_coverage_service (line 439) | def configure_coverage_service
method configure_coverage_access_token (line 443) | def configure_coverage_access_token
method coverage_service= (line 447) | def coverage_service=(service)
method configure_binary_file (line 474) | def configure_binary_file
method configure_arch (line 480) | def configure_arch
method decimal_f (line 484) | def decimal_f decimal_arg
method find_binary_file_in_bundle (line 491) | def find_binary_file_in_bundle(bundle_file)
method find_binary_files (line 509) | def find_binary_files
method find_buildable_names (line 616) | def find_buildable_names(xcscheme)
method matches_arch (line 660) | def matches_arch(binary_path)
method find_source_files (line 670) | def find_source_files
method load_option_array (line 684) | def load_option_array(option)
FILE: lib/slather/version.rb
type Slather (line 1) | module Slather
FILE: spec/slather/coverage_service/html_output_spec.rb
function extract_header_title (line 45) | def extract_header_title(doc)
function extract_title (line 75) | def extract_title(doc)
function extract_coverage_text (line 79) | def extract_coverage_text(doc)
function extract_coverage_class (line 83) | def extract_coverage_class(doc)
function extract_cov_header (line 87) | def extract_cov_header(doc)
function extract_cov_index (line 93) | def extract_cov_index(doc)
function extract_title (line 129) | def extract_title(doc)
function extract_subtitle (line 133) | def extract_subtitle(doc)
function extract_filepath (line 137) | def extract_filepath(doc)
function extract_cov_data (line 141) | def extract_cov_data(doc)
function extract_filepath (line 183) | def extract_filepath(doc)
FILE: spec/slather/project_spec.rb
class SpecCoverageFile (line 39) | class SpecCoverageFile < Slather::CoverageFile
class SpecXcode7CoverageFile (line 68) | class SpecXcode7CoverageFile < Slather::ProfdataCoverageFile
class SpecXcode7CoverageFile (line 135) | class SpecXcode7CoverageFile < Slather::ProfdataCoverageFile
function decimal_f (line 692) | def decimal_f *args
FILE: spec/spec_helper.rb
type FixtureHelpers (line 30) | module FixtureHelpers
function delete_derived_data (line 31) | def self.delete_derived_data
function delete_temp_gcov_files (line 38) | def self.delete_temp_gcov_files
Condensed preview — 95 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (385K chars).
[
{
"path": ".coveralls.yml",
"chars": 23,
"preview": "service_name: travis-ci"
},
{
"path": ".gitignore",
"chars": 611,
"preview": "*.gem\n*.rbc\n.bundle\n.config\n.yardoc\nGemfile.lock\nInstalledFiles\n_yardoc\ncoverage\ndoc/\nlib/bundler/man\npkg\nrdoc\nspec/repo"
},
{
"path": ".travis.yml",
"chars": 278,
"preview": "language: objective-c\nscript: bundle exec rake\nosx_image: xcode12.2\n\ncache: bundler\n\nbefore_install:\n - curl http://cur"
},
{
"path": "CHANGELOG.md",
"chars": 19176,
"preview": "# CHANGELOG\n\n## v2.8.5\n\n* Update xcodeproj to 1.27.1 to support Xcode 16 folder references\n [authiatr](https://github.c"
},
{
"path": "Gemfile",
"chars": 92,
"preview": "source 'https://rubygems.org'\n\n# Specify your gem's dependencies in slather.gemspec\ngemspec\n"
},
{
"path": "LICENSE.txt",
"chars": 1068,
"preview": "Copyright (c) 2014 Mark Larsen\n\nMIT License\n\nPermission is hereby granted, free of charge, to any person obtaining\na cop"
},
{
"path": "README.md",
"chars": 10728,
"preview": "\n\n\n\n[\n\ntask default: :spec\n"
},
{
"path": "assets/highlight.pack.js",
"chars": 11432,
"preview": "!function(e){\"undefined\"!=typeof exports?e(exports):(window.hljs=e({}),\"function\"==typeof define&&define.amd&&define(\"hl"
},
{
"path": "assets/slather.css",
"chars": 6331,
"preview": "/* --------------------------------------------------------\nSlather stylesheet\n\nversion: 0.1\nauthor: Ikhsan Assaat (@ixn"
},
{
"path": "bin/slather",
"chars": 598,
"preview": "#!/usr/bin/env ruby\nrequire 'clamp'\nrequire 'yaml'\nrequire_relative '../lib/slather'\nrequire_relative '../lib/slather/co"
},
{
"path": "lib/cocoapods_plugin.rb",
"chars": 314,
"preview": "require_relative 'slather'\n\nPod::HooksManager.register('slather', :post_install) do |installer_context|\n sandbox_root ="
},
{
"path": "lib/slather/command/coverage_command.rb",
"chars": 6402,
"preview": "class CoverageCommand < Clamp::Command\n\n parameter \"[PROJECT]\", \"Path to the xcodeproj\", :attribute_name => :xcodeproj_"
},
{
"path": "lib/slather/command/setup_command.rb",
"chars": 828,
"preview": "class SetupCommand < Clamp::Command\n parameter \"[PROJECT]\", \"Path to the .xcodeproj\", :attribute_name => :xcodeproj_pat"
},
{
"path": "lib/slather/command/version_command.rb",
"chars": 102,
"preview": "class VersionCommand < Clamp::Command\n\n def execute\n puts \"slather #{Slather::VERSION}\"\n end\nend\n"
},
{
"path": "lib/slather/coverage_file.rb",
"chars": 4024,
"preview": "require_relative 'coverage_info'\nrequire_relative 'coveralls_coverage'\n\nmodule Slather\n class CoverageFile\n\n include"
},
{
"path": "lib/slather/coverage_info.rb",
"chars": 2458,
"preview": "module Slather\n module CoverageInfo\n\n def num_lines_tested\n line_coverage_data.compact.select { |cd| cd > 0 }.c"
},
{
"path": "lib/slather/coverage_service/cobertura_xml_output.rb",
"chars": 7362,
"preview": "require 'nokogiri'\nrequire 'date'\n\nmodule Slather\n module CoverageService\n module CoberturaXmlOutput\n\n def cove"
},
{
"path": "lib/slather/coverage_service/coveralls.rb",
"chars": 12320,
"preview": "module Slather\n module CoverageService\n module Coveralls\n\n def coverage_file_class\n if input_format == \""
},
{
"path": "lib/slather/coverage_service/gutter_json_output.rb",
"chars": 1553,
"preview": "module Slather\n module CoverageService\n module GutterJsonOutput\n\n def coverage_file_class\n if input_form"
},
{
"path": "lib/slather/coverage_service/hardcover.rb",
"chars": 1793,
"preview": "module Slather\n module CoverageService\n module Hardcover\n\n def coverage_file_class\n if input_format == \""
},
{
"path": "lib/slather/coverage_service/html_output.rb",
"chars": 12439,
"preview": "require 'nokogiri'\nrequire \"cgi\"\n\nmodule Slather\n module CoverageService\n module HtmlOutput\n\n attr_reader :docs"
},
{
"path": "lib/slather/coverage_service/json_output.rb",
"chars": 859,
"preview": "require 'nokogiri'\nrequire 'date'\n\nmodule Slather\n module CoverageService\n module JsonOutput\n\n def coverage_fil"
},
{
"path": "lib/slather/coverage_service/llvm_cov_output.rb",
"chars": 868,
"preview": "require 'nokogiri'\nrequire 'date'\n\nmodule Slather\n module CoverageService\n module LlvmCovOutput\n\n def coverage_"
},
{
"path": "lib/slather/coverage_service/simple_output.rb",
"chars": 2189,
"preview": "module Slather\n module CoverageService\n module SimpleOutput\n\n def coverage_file_class\n if input_format ="
},
{
"path": "lib/slather/coverage_service/sonarqube_xml_output.rb",
"chars": 1781,
"preview": "require 'nokogiri'\nrequire 'date'\n\nmodule Slather\n module CoverageService\n module SonarqubeXmlOutput\n\n def cove"
},
{
"path": "lib/slather/coveralls_coverage.rb",
"chars": 232,
"preview": "module Slather\n module CoverallsCoverage\n\n def as_json\n {\n :name => source_file_pathname_relative_to_rep"
},
{
"path": "lib/slather/profdata_coverage_file.rb",
"chars": 6906,
"preview": "require_relative 'coverage_info'\nrequire_relative 'coveralls_coverage'\nrequire 'digest/md5'\n\nmodule Slather\n class Prof"
},
{
"path": "lib/slather/project.rb",
"chars": 25633,
"preview": "require 'fileutils'\nrequire 'xcodeproj'\nrequire 'json'\nrequire 'yaml'\nrequire 'shellwords'\n\nmodule Xcodeproj\n\n class Pr"
},
{
"path": "lib/slather/version.rb",
"chars": 73,
"preview": "module Slather\n VERSION = '2.8.5' unless defined?(Slather::VERSION)\nend\n"
},
{
"path": "lib/slather.rb",
"chars": 1322,
"preview": "require_relative 'slather/version'\nrequire_relative 'slather/project'\nrequire_relative 'slather/coverage_info'\nrequire_r"
},
{
"path": "slather.gemspec",
"chars": 1483,
"preview": "# encoding: utf-8\nlib = File.expand_path('../lib', __FILE__)\n$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)\nreq"
},
{
"path": "spec/fixtures/FixtureFramework/FixtureFramework.h",
"chars": 557,
"preview": "//\n// FixtureFramework.h\n// FixtureFramework\n//\n// Created by Stephen Williams on 11/03/21.\n// Copyright © 2021 mark"
},
{
"path": "spec/fixtures/FixtureFramework/FlashExperiment.swift",
"chars": 111,
"preview": "import Foundation\n\npublic struct FlashExperiment {\n public let isAwesome = true\n \n public init() {}\n}\n"
},
{
"path": "spec/fixtures/FixtureFramework/Info.plist",
"chars": 855,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "spec/fixtures/FixtureFrameworkTests/FixtureFrameworkTests.swift",
"chars": 986,
"preview": "//\n// FixtureFrameworkTests.swift\n// FixtureFrameworkTests\n//\n// Created by Stephen Williams on 11/03/21.\n// Copyrig"
},
{
"path": "spec/fixtures/FixtureFrameworkTests/FlashExperimentTests.swift",
"chars": 233,
"preview": "import XCTest\nimport FixtureFramework\n\nclass FlashExperimentTests: XCTestCase {\n func testExample() throws {\n "
},
{
"path": "spec/fixtures/FixtureFrameworkTests/Info.plist",
"chars": 727,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "spec/fixtures/fixtures/Fixtures.swift",
"chars": 347,
"preview": "\nimport UIKit\n\n@UIApplicationMain\nclass AppDelegate: UIResponder, UIApplicationDelegate {\n\n var window: UIWindow?\n\n "
},
{
"path": "spec/fixtures/fixtures/Supporting Files/fixtures-Prefix.pch",
"chars": 172,
"preview": "//\n// Prefix header\n//\n// The contents of this file are implicitly included at the beginning of every source file.\n//\n"
},
{
"path": "spec/fixtures/fixtures/fixtures.h",
"chars": 250,
"preview": "//\n// fixtures.h\n// fixtures\n//\n// Created by Mark Larsen on 6/24/14.\n// Copyright (c) 2014 marklarr. All rights res"
},
{
"path": "spec/fixtures/fixtures/fixtures.m",
"chars": 286,
"preview": "//\n// fixtures.m\n// fixtures\n//\n// Created by Mark Larsen on 6/24/14.\n// Copyright (c) 2014 marklarr 🌟. All rights r"
},
{
"path": "spec/fixtures/fixtures/fixtures_cpp.cpp",
"chars": 163,
"preview": "//\n// fixtures_cpp.cpp\n// fixtures\n//\n// Created by Larsen, Mark on 4/3/15.\n// Copyright (c) 2015 marklarr. All righ"
},
{
"path": "spec/fixtures/fixtures/fixtures_cpp.h",
"chars": 140,
"preview": "#ifndef __fixtures__fixtures_cpp__\n#define __fixtures__fixtures_cpp__\n\n#include <stdio.h>\n\n#endif /* defined(__fixtures_"
},
{
"path": "spec/fixtures/fixtures/fixtures_m.h",
"chars": 74,
"preview": "#import <Foundation/Foundation.h>\n\n@interface fixtures_m : NSObject\n\n@end\n"
},
{
"path": "spec/fixtures/fixtures/fixtures_m.m",
"chars": 57,
"preview": "#import \"fixtures_m.h\"\n\n@implementation fixtures_m\n\n@end\n"
},
{
"path": "spec/fixtures/fixtures/fixtures_mm.h",
"chars": 75,
"preview": "#import <Foundation/Foundation.h>\n\n@interface fixtures_mm : NSObject\n\n@end\n"
},
{
"path": "spec/fixtures/fixtures/fixtures_mm.mm",
"chars": 59,
"preview": "#import \"fixtures_mm.h\"\n\n@implementation fixtures_mm\n\n@end\n"
},
{
"path": "spec/fixtures/fixtures/more_files/Branches.h",
"chars": 268,
"preview": "//\n// Branches.h\n// fixtures\n//\n// Created by Julian Krumow on 11.10.14.\n// Copyright (c) 2014 marklarr. All rights "
},
{
"path": "spec/fixtures/fixtures/more_files/Branches.m",
"chars": 731,
"preview": "//\n// Branches.m\n// fixtures\n//\n// Created by Julian Krumow on 11.10.14.\n// Copyright (c) 2014 marklarr. All rights "
},
{
"path": "spec/fixtures/fixtures/more_files/Empty.h",
"chars": 200,
"preview": "//\n// Empty.h\n// fixtures\n//\n// Created by Julian Krumow on 27.10.14.\n// Copyright (c) 2014 marklarr. All rights res"
},
{
"path": "spec/fixtures/fixtures/more_files/Empty.m",
"chars": 178,
"preview": "//\n// Empty.m\n// fixtures\n//\n// Created by Julian Krumow on 27.10.14.\n// Copyright (c) 2014 marklarr. All rights res"
},
{
"path": "spec/fixtures/fixtures/more_files/peekaview.h",
"chars": 195,
"preview": "//\n// peekaview.h\n// fixtures\n//\n// Created by Mark Larsen on 6/25/14.\n// Copyright (c) 2014 marklarr. All rights re"
},
{
"path": "spec/fixtures/fixtures/more_files/peekaview.m",
"chars": 530,
"preview": "//\n// peekaview.m\n// fixtures\n//\n// Created by Mark Larsen on 6/25/14.\n// Copyright (c) 2014 marklarr. All rights re"
},
{
"path": "spec/fixtures/fixtures/other_fixtures.m",
"chars": 302,
"preview": "//\n// other_fixtures.m\n// fixtures\n//\n// Created by Mark Larsen on 6/24/14.\n// Copyright (c) 2014 marklarr. All righ"
},
{
"path": "spec/fixtures/fixtures.xcodeproj/project.pbxproj",
"chars": 40265,
"preview": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXBuildFile section *"
},
{
"path": "spec/fixtures/fixtures.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
"chars": 153,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n version = \"1.0\">\n <FileRef\n location = \"self:fixtures.xcodep"
},
{
"path": "spec/fixtures/fixtures.xcodeproj/xcshareddata/xcschemes/aggregateFixturesTests.xcscheme",
"chars": 4179,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n LastUpgradeVersion = \"0730\"\n version = \"1.3\">\n <BuildAction\n "
},
{
"path": "spec/fixtures/fixtures.xcodeproj/xcshareddata/xcschemes/fixtures.xcscheme",
"chars": 3651,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n LastUpgradeVersion = \"0600\"\n version = \"1.3\">\n <BuildAction\n "
},
{
"path": "spec/fixtures/fixtures.xcodeproj/xcshareddata/xcschemes/fixturesTests.xcscheme",
"chars": 1922,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n LastUpgradeVersion = \"0600\"\n version = \"1.3\">\n <BuildAction\n "
},
{
"path": "spec/fixtures/fixtures.xcodeproj/xcshareddata/xcschemes/fixturesTestsSecond.xcscheme",
"chars": 3746,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n LastUpgradeVersion = \"0600\"\n version = \"1.3\">\n <BuildAction\n "
},
{
"path": "spec/fixtures/fixtures.xcodeproj/xcshareddata/xcschemes/fixturesTwo.xcscheme",
"chars": 2874,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n LastUpgradeVersion = \"0730\"\n version = \"1.3\">\n <BuildAction\n "
},
{
"path": "spec/fixtures/fixtures.xcworkspace/contents.xcworkspacedata",
"chars": 154,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n version = \"1.0\">\n <FileRef\n location = \"group:fixtures.xcode"
},
{
"path": "spec/fixtures/fixtures.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist",
"chars": 238,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "spec/fixtures/fixtures.xcworkspace/xcshareddata/xcschemes/fixturesTestsWorkspace.xcscheme",
"chars": 3638,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n LastUpgradeVersion = \"0730\"\n version = \"1.3\">\n <BuildAction\n "
},
{
"path": "spec/fixtures/fixturesTests/BranchesTests.m",
"chars": 834,
"preview": "//\n// BranchesTests.m\n// fixtures\n//\n// Created by Julian Krumow on 11.10.14.\n// Copyright (c) 2014 marklarr. All ri"
},
{
"path": "spec/fixtures/fixturesTests/Supporting Files/en.lproj/InfoPlist.strings",
"chars": 45,
"preview": "/* Localized versions of Info.plist keys */\n\n"
},
{
"path": "spec/fixtures/fixturesTests/Supporting Files/fixturesTests-Info.plist",
"chars": 688,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "spec/fixtures/fixturesTests/fixturesTests.m",
"chars": 802,
"preview": "//\n// fixturesTests.m\n// fixturesTests\n//\n// Created by Mark Larsen on 6/24/14.\n// Copyright (c) 2014 marklarr. All "
},
{
"path": "spec/fixtures/fixturesTests/fixturesTestsSecond.m",
"chars": 292,
"preview": "//\n// fixturesTestsSecond.m\n// fixturesTests\n//\n// Created by Mark Larsen on 6/24/14.\n// Copyright (c) 2014 marklarr"
},
{
"path": "spec/fixtures/fixturesTests/peekaviewTests💣.m",
"chars": 598,
"preview": "//\n// peekaviewTests💣.m\n// fixtures\n//\n// Created by Mark Larsen on 6/25/14.\n// Copyright (c) 2014 marklarr. All rig"
},
{
"path": "spec/fixtures/fixturesTwo/fixturesTwo.h",
"chars": 241,
"preview": "//\n// fixturesTwo.h\n// fixturesTwo\n//\n// Created by Kent Sutherland on 4/17/16.\n// Copyright © 2016 marklarr. All ri"
},
{
"path": "spec/fixtures/fixturesTwo/fixturesTwo.m",
"chars": 289,
"preview": "//\n// fixturesTwo.m\n// fixturesTwo\n//\n// Created by Kent Sutherland on 4/17/16.\n// Copyright © 2016 marklarr. All ri"
},
{
"path": "spec/fixtures/fixtures_html/Branches.m.html",
"chars": 7750,
"preview": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\" \"http://www.w3.org/TR/REC-html40/loose.dtd\">\n<html>\n<head>"
},
{
"path": "spec/fixtures/fixtures_html/BranchesTests.m.html",
"chars": 6910,
"preview": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\" \"http://www.w3.org/TR/REC-html40/loose.dtd\">\n<html>\n<head>"
},
{
"path": "spec/fixtures/fixtures_html/fixtures.m.html",
"chars": 4284,
"preview": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\" \"http://www.w3.org/TR/REC-html40/loose.dtd\">\n<html>\n<head>"
},
{
"path": "spec/fixtures/fixtures_html/fixturesTests.m.html",
"chars": 7686,
"preview": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\" \"http://www.w3.org/TR/REC-html40/loose.dtd\">\n<html>\n<head>"
},
{
"path": "spec/fixtures/fixtures_html/index.html",
"chars": 2910,
"preview": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\" \"http://www.w3.org/TR/REC-html40/loose.dtd\">\n<html>\n<head>"
},
{
"path": "spec/fixtures/fixtures_html/peekaviewTests💣.m.html",
"chars": 6156,
"preview": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\" \"http://www.w3.org/TR/REC-html40/loose.dtd\">\n<html>\n<head>"
},
{
"path": "spec/fixtures/gutter.json",
"chars": 10756,
"preview": "{\"meta\":{\"timestamp\":\"2016-04-17 16:53:43.919308\"},\"symbols_by_file\":{\"spec/fixtures/fixtures/fixtures.m\":[{\"line\":1,\"lo"
},
{
"path": "spec/fixtures/sonarqube-generic-coverage.xml",
"chars": 4428,
"preview": "<?xml version=\"1.0\"?>\n<coverage version=\"1\">\n <file path=\"spec/fixtures/fixtures/fixtures.m\">\n <lineToCover lineNumb"
},
{
"path": "spec/slather/cocoapods_plugin_spec.rb",
"chars": 821,
"preview": "require 'cocoapods'\nrequire File.join(File.dirname(__FILE__), '..', 'spec_helper')\nrequire File.join(File.dirname(__FILE"
},
{
"path": "spec/slather/coverage_file_spec.rb",
"chars": 12567,
"preview": "require File.join(File.dirname(__FILE__), '..', 'spec_helper')\n\ndescribe Slather::CoverageFile do\n\n let(:fixtures_proje"
},
{
"path": "spec/slather/coverage_service/cobertura_xml_spec.rb",
"chars": 1570,
"preview": "require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper')\nrequire 'json'\n\ndescribe Slather::CoverageService::"
},
{
"path": "spec/slather/coverage_service/coveralls_spec.rb",
"chars": 13581,
"preview": "require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper')\n\ndescribe Slather::CoverageService::Coveralls do\n\n "
},
{
"path": "spec/slather/coverage_service/gutter_json_spec.rb",
"chars": 919,
"preview": "require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper')\nrequire 'json'\n\ndescribe Slather::CoverageService::"
},
{
"path": "spec/slather/coverage_service/hardcover_spec.rb",
"chars": 4471,
"preview": "require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper')\n\ndescribe Slather::CoverageService::Hardcover do\n\n "
},
{
"path": "spec/slather/coverage_service/html_output_spec.rb",
"chars": 7173,
"preview": "require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper')\nrequire 'nokogiri'\n\ndescribe Slather::CoverageServi"
},
{
"path": "spec/slather/coverage_service/json_spec.rb",
"chars": 1307,
"preview": "require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper')\nrequire 'json'\n\ndescribe Slather::CoverageService::"
},
{
"path": "spec/slather/coverage_service/llvm_cov_spec.rb",
"chars": 1425,
"preview": "require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper')\n\ndescribe Slather::CoverageService::LlvmCovOutput d"
},
{
"path": "spec/slather/coverage_service/simple_output_spec.rb",
"chars": 2449,
"preview": "require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper')\n\ndescribe Slather::CoverageService::SimpleOutput do"
},
{
"path": "spec/slather/coverage_service/sonarqube_xml_spec.rb",
"chars": 1389,
"preview": "require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper')\nrequire 'json'\n\ndescribe Slather::CoverageService::"
},
{
"path": "spec/slather/profdata_coverage_spec.rb",
"chars": 9704,
"preview": "require File.join(File.dirname(__FILE__), '..', 'spec_helper')\n\ndescribe Slather::ProfdataCoverageFile do\n\n let(:fixtur"
},
{
"path": "spec/slather/project_spec.rb",
"chars": 32763,
"preview": "require File.join(File.dirname(__FILE__), '..', 'spec_helper')\n\ndescribe Slather::Project do\n\n FIXTURES_PROJECT_SETUP_P"
},
{
"path": "spec/spec_helper.rb",
"chars": 2445,
"preview": "if ENV['SIMPLECOV']\n require 'simplecov'\n SimpleCov.start\nelsif ENV['TRAVIS']\n require 'coveralls'\n Coveralls.wear!\n"
}
]
About this extraction
This page contains the full source code of the venmo/slather GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 95 files (348.6 KB), approximately 100.6k tokens, and a symbol index with 284 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.