lib/slather/project.rb in slather-2.4.5 vs lib/slather/project.rb in slather-2.4.6

- old
+ new

@@ -116,28 +116,30 @@ end private :gcov_coverage_files def profdata_coverage_files coverage_files = [] - source_files = find_source_files || [] line_numbers_first = Gem::Version.new(self.llvm_version) >= Gem::Version.new('8.1.0') if self.binary_file self.binary_file.each do |binary_path| - files = profdata_llvm_cov_output(binary_path, source_files).split("\n\n") + coverage_json_string = llvm_cov_export_output(binary_path) + coverage_json = JSON.parse(coverage_json_string) + pathnames_per_binary = coverage_json["data"].reduce([]) do |result, chunk| + result.concat(chunk["files"].map do |file| + Pathname(file["filename"]).realpath + end) + end + files = profdata_llvm_cov_output(binary_path, pathnames_per_binary).split("\n\n") + coverage_files.concat(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 = source_files.first if source_files.count == 1 + coverage_file.source_file_pathname = pathnames_per_binary.first if pathnames_per_binary.count == 1 !coverage_file.ignored? ? coverage_file : nil end.compact) - - if !source_files.empty? - coverage_file_paths = coverage_files.map { |file| file.source_file_pathname }.to_set - source_files.select! { |path| !coverage_file_paths.include?(path) } - end end end coverage_files end @@ -199,10 +201,34 @@ 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 @@ -441,19 +467,20 @@ 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)) - }.reject { |path| - path.end_with? ".dSYM" - path.end_with? ".swiftmodule" + }.find { |path| + next if path.end_with? ".dSYM" + next if path.end_with? ".swiftmodule" - if path and File.directory? path + if File.directory? path path = find_binary_file_in_bundle(path) + next if path.nil? end - !matches_arch(path) - }.first + 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