lib/slather/project.rb in slather-2.3.0 vs lib/slather/project.rb in slather-2.4.0

- old
+ new

@@ -50,11 +50,11 @@ 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, :verbose_mode, :input_format, :scheme, :workspace, :binary_file, :binary_basename, :source_files, - :decimals + :decimals, :llvm_version alias_method :setup_for_coverage, :slather_setup_for_coverage def self.open(xcodeproj) proj = super @@ -82,11 +82,11 @@ schemeArgument = nil buildAction = nil end # redirect stderr to avoid xcodebuild errors being printed. - build_settings = `xcodebuild #{projectOrWorkspaceArgument} #{schemeArgument} -showBuildSettings #{buildAction} 2>&1` + 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 @@ -124,17 +124,18 @@ 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_files.concat(files.map do |source| - coverage_file = coverage_file_class.new(self, 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.ignored? ? coverage_file : nil end.compact) @@ -206,11 +207,12 @@ `xcrun llvm-cov #{llvm_cov_args.shelljoin} #{source_files.shelljoin}` end private :unsafe_profdata_llvm_cov_output def profdata_llvm_cov_output(binary_path, source_files) - unsafe_profdata_llvm_cov_output(binary_path, source_files).encode!('UTF-8', 'binary', :invalid => :replace, undef: :replace) + 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) } @@ -237,10 +239,12 @@ configure_source_directory configure_output_directory configure_input_format configure_binary_file configure_decimals + + self.llvm_version = `xcrun llvm-cov --version`.match(/Apple LLVM version ([\d\.]+)/).captures[0] rescue => e puts e.message puts failure_help_string puts "\n" raise @@ -389,24 +393,13 @@ raise StandardError, "No scheme named '#{self.scheme}' found in #{self.path}" unless File.exists? xcscheme_path xcscheme = Xcodeproj::XCScheme.new(xcscheme_path) - begin - buildable_name = xcscheme.build_action.entries[0].buildable_references[0].buildable_name - rescue - # xcodeproj will raise an exception if there are no entries in the build action - end - - if buildable_name == nil or buildable_name.end_with? ".a" - # Can't run code coverage on static libraries, look for an associated test bundle - buildable_name = xcscheme.test_action.testables[0].buildable_references[0].buildable_name - end - configuration = xcscheme.test_action.build_configuration - search_list = binary_basename || [buildable_name] + search_list = binary_basename || find_buildable_names(xcscheme) search_list.each do |search_for| found_product = Dir["#{profdata_coverage_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 @@ -457,9 +450,40 @@ 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 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 find_source_files source_files = load_option_array("source_files") return if source_files.nil?