From 6967230163a200aeb66373ce1c703577ae4f19fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gae=CC=88l=20Foppolo?= Date: Sat, 31 Aug 2019 21:16:48 +0200 Subject: [PATCH 01/30] Begin to write a Ruby script, more robust than Shell script --- analyzer/Gemfile | 3 ++ analyzer/Gemfile.lock | 13 ++++++++ analyzer/canfail.rb | 8 +++++ analyzer/logging.rb | 29 +++++++++++++++++ analyzer/main.rb | 60 +++++++++++++++++++++++++++++++++++ analyzer/options.rb | 46 +++++++++++++++++++++++++++ analyzer/properties_reader.rb | 50 +++++++++++++++++++++++++++++ analyzer/swiftlint.rb | 35 ++++++++++++++++++++ analyzer/tool.rb | 29 +++++++++++++++++ 9 files changed, 273 insertions(+) create mode 100644 analyzer/Gemfile create mode 100644 analyzer/Gemfile.lock create mode 100644 analyzer/canfail.rb create mode 100644 analyzer/logging.rb create mode 100644 analyzer/main.rb create mode 100644 analyzer/options.rb create mode 100644 analyzer/properties_reader.rb create mode 100644 analyzer/swiftlint.rb create mode 100644 analyzer/tool.rb diff --git a/analyzer/Gemfile b/analyzer/Gemfile new file mode 100644 index 00000000..227da0d1 --- /dev/null +++ b/analyzer/Gemfile @@ -0,0 +1,3 @@ +source 'https://rubygems.org' + +gem 'java-properties', "= 0.2.0" \ No newline at end of file diff --git a/analyzer/Gemfile.lock b/analyzer/Gemfile.lock new file mode 100644 index 00000000..7bfecb52 --- /dev/null +++ b/analyzer/Gemfile.lock @@ -0,0 +1,13 @@ +GEM + remote: https://rubygems.org/ + specs: + java-properties (0.2.0) + +PLATFORMS + ruby + +DEPENDENCIES + java-properties (= 0.2.0) + +BUNDLED WITH + 2.0.2 diff --git a/analyzer/canfail.rb b/analyzer/canfail.rb new file mode 100644 index 00000000..8893d28c --- /dev/null +++ b/analyzer/canfail.rb @@ -0,0 +1,8 @@ +# Adds a fatal_error method that logs and exit. +# This module expects the Logging module included. +module CanFail + def fatal_error(msg) + logger.error(msg) + exit(false) + end +end diff --git a/analyzer/logging.rb b/analyzer/logging.rb new file mode 100644 index 00000000..82486339 --- /dev/null +++ b/analyzer/logging.rb @@ -0,0 +1,29 @@ +require 'logger' + +# Adds logging capability where included. +module Logging + def logger + @logger ||= Logging.logger_for(self.class.name) + end + + # Use a hash class-ivar to cache a unique Logger per class: + @@loggers = {} + @@logger_level = Logger::INFO + + class << self + def logger_for(classname) + @@loggers[classname] ||= configure_logger_for(classname) + end + + def configure_logger_for(classname) + logger = Logger.new(STDOUT) + logger.progname = classname + logger.level = @@logger_level + logger + end + + def logger_level=(level) + @@logger_level = level + end + end +end \ No newline at end of file diff --git a/analyzer/main.rb b/analyzer/main.rb new file mode 100644 index 00000000..a73566bf --- /dev/null +++ b/analyzer/main.rb @@ -0,0 +1,60 @@ +#!/usr/bin/env ruby +require 'ostruct' +require_relative 'logging' +require_relative 'swiftlint' +require_relative 'options' +require_relative 'properties_reader' + +# Entry point of the script. +# +# It reads the configurations, run all analytic tools and send reports +# to Sonar. +class RunSonarSwift + include Logging + + def run + options = OpenStruct.new + # list of tools by default + options.tools = [SwiftLint] + # upload results to SonarQube by default + options.upload = true + # upload results to SonarQube by default + options.path = 'sonar-project.properties' + + # read CLI arguments and update configuration + Options.new.parse(ARGV, options) + + # Read properties + properties = SonarPropertiesReader.new(options.path).read + + # Initiate reports + # TODO + + # Filter tools by availability + options.tools = available_tools(options.tools) + + # Run tools + options.tools.each do |tool| + tool.new(properties).run + end + + # Send reports + # TODO + + end + + # Check each tool is available and return an updated list of tool. + def available_tools(tools) + tools.select do |tool| + if tool.availability + true + else + logger.warn("#{tool.command} is not found in PATH and won't be available in reports.") + false + end + end + end + +end + +RunSonarSwift.new.run diff --git a/analyzer/options.rb b/analyzer/options.rb new file mode 100644 index 00000000..041a131b --- /dev/null +++ b/analyzer/options.rb @@ -0,0 +1,46 @@ +require 'optparse' + +class Options + + # + # Return a structure describing the options. + # + def parse(args, options) + # The options specified on the command line will be updated in *options*. + + opt_parser = OptionParser.new do |opts| + opts.banner = "Usage: main.rb [options]" + + opts.separator "" + opts.separator "Specific options:" + + opts.on("-v", "--verbose", "Run verbosely") do |_| + Logging.logger_level = Logger::DEBUG + end + + # Optional + opts.on("--disable-swiftlint", "Disable SwiftLint") do |_| + options.tools.delete_at(options.tools.index(SwiftLint)) + end + + # Optional + opts.on("-p", "--path PATH", String, "Path to properties file.") do |p| + options.path = p + end + + opts.separator "" + opts.separator "Common options:" + + # No argument, shows at tail. This will print an options summary. + # Try it and see! + opts.on_tail("-h", "--help", "Show this message") do + puts opts + exit + end + end + + opt_parser.parse!(args) + + end # parse() + +end # class OptparseExample \ No newline at end of file diff --git a/analyzer/properties_reader.rb b/analyzer/properties_reader.rb new file mode 100644 index 00000000..359ce229 --- /dev/null +++ b/analyzer/properties_reader.rb @@ -0,0 +1,50 @@ +require_relative 'logging' +require_relative 'canfail' +require 'fileutils' +require 'java-properties' + +# SonarPropertiesReader reads and check the sonar-project.properties file. +# It also creates a Hash with all read properties. +class SonarPropertiesReader + include Logging + include CanFail + + def initialize(path) + fatal_error("No #{path} found") unless File.exist?(path) + @file = path + end + + # Read the Java properties file and return a Hash suitable for the script. + def read + logger.info('Reading Sonar project properties...') + properties = JavaProperties.load(@file) + options = read_properties(properties) + validate_settings!(options) + end + + private + + # Map the Java properties hash to more Ruby hash + def read_properties(properties) + options = {} + options[:project] = properties[:'sonar.swift.project'] + options[:workspace] = properties[:'sonar.swift.workspace'] + options[:sources] = properties[:'sonar.sources'].split(',') + options[:scheme] = properties[:'sonar.swift.appScheme'] + options[:configuration] = properties[:'sonar.swift.appConfiguration'] + options[:simulator] = properties[:'sonar.swift.simulator'] + options[:exclude_from_coverage] = properties[:'sonar.swift.excludedPathsFromCoverage'].split(',') + options + end + + def validate_settings!(options) + fatal_error('No project or workspace specified.') if (options[:workspace].nil? && options[:project].nil?) + fatal_error('No sources folder specified.') if options[:sources].nil? + fatal_error('No scheme specified.') if options[:scheme].nil? + if options[:configuration].nil? + logger.warn('No build configuration set, defaulting to Debug') + options[:configuration] = 'Debug' + end + options + end +end \ No newline at end of file diff --git a/analyzer/swiftlint.rb b/analyzer/swiftlint.rb new file mode 100644 index 00000000..dee9a79f --- /dev/null +++ b/analyzer/swiftlint.rb @@ -0,0 +1,35 @@ +require_relative 'tool' + +# SwiftLint checks code style and conventions. +# +# It is mainly based on the [Swift Style +# Guide](https://github.com/github/swift-style-guide) and it may also be +# used to enforce custom conventions. +# +# https://github.com/realm/SwiftLint +class SwiftLint < Tool + def self.command + 'swiftlint' + end + + def initialize(options) + @sources = options[:sources] + super(options) + end + + def run() + logger.info('Running SwiftLint...') + @sources.each do |source| + report_name = "#{source.tr(' ', '_')}-swiftlint.txt" + cmd = "#{self.class.command} lint --path #{source} > sonar-reports/#{report_name}" + logger.info("Will run `#{cmd}`") + system(cmd) + end + end + + private + + def validate_settings! + fatal_error('SwiftLint: Sources must be set.') if @sources.nil? + end +end \ No newline at end of file diff --git a/analyzer/tool.rb b/analyzer/tool.rb new file mode 100644 index 00000000..5a31cc02 --- /dev/null +++ b/analyzer/tool.rb @@ -0,0 +1,29 @@ +require_relative 'logging' +require_relative 'canfail' + +# A base class for tool wrappers. +# +# Mainly defines a common interface + includes some useful modules. +class Tool + include Logging + include CanFail + + def self.command + end + + def initialize(_options) + validate_settings! + end + + def run + end + + protected + def self.availability + system("which #{self.command} 2>&1 > /dev/null") + end + + protected + def validate_settings! + end +end \ No newline at end of file From 554214cd235c8f6add7d33c521222006acc7d931 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gae=CC=88l=20Foppolo?= Date: Sun, 1 Sep 2019 14:53:50 +0200 Subject: [PATCH 02/30] Update Options parser to support report argument. --- analyzer/options.rb | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/analyzer/options.rb b/analyzer/options.rb index 041a131b..d83b62a3 100644 --- a/analyzer/options.rb +++ b/analyzer/options.rb @@ -2,6 +2,8 @@ class Options + REPORTER_ALIASES = { :scanner => "SonarScanner", :runner => "SonarRunner" } + # # Return a structure describing the options. # @@ -26,6 +28,12 @@ def parse(args, options) # Optional opts.on("-p", "--path PATH", String, "Path to properties file.") do |p| options.path = p + end + + # Optional + opts.on("-r", "--reporter [REPORTER]", REPORTER_ALIASES.keys, + "Select Sonar reporter (scanner, runner)") do |r| + options.reporter = REPORTER_ALIASES[r] end opts.separator "" @@ -41,6 +49,6 @@ def parse(args, options) opt_parser.parse!(args) - end # parse() + end -end # class OptparseExample \ No newline at end of file +end \ No newline at end of file From 83e3b0ed4593d04169db7c4ca176154ed1419904 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gae=CC=88l=20Foppolo?= Date: Sun, 1 Sep 2019 14:54:23 +0200 Subject: [PATCH 03/30] Add Helper class to handle common tasks --- analyzer/helper.rb | 56 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 analyzer/helper.rb diff --git a/analyzer/helper.rb b/analyzer/helper.rb new file mode 100644 index 00000000..4aeb05bb --- /dev/null +++ b/analyzer/helper.rb @@ -0,0 +1,56 @@ +require 'fileutils' +require_relative 'logging' + +class Helper + include Logging + + # Put default xml files with no tests and no coverage. This is needed to + # ensure a file is present, either the Xcode build test step worked or + # not. Without this, Sonar Scanner will fail uploading results. + def bootstrap_reports + reports_folder + mandatory_reports + end + + # Check each program is available and return an updated list. + def available(programs) + case programs + when Array + programs.select do |program| + _available(program) unless nil + end + else + _available(programs) + end + end + + # Check program is available and return an updated list. + private + def _available(program) + if program.availability + program + else + logger.warn("#{program.command} is not found in PATH.") + nil + end + end + + private + def mandatory_reports + logger.info('Creating default reports') + empty_test_report = "" + File.write('sonar-reports/TEST-report.xml', empty_test_report) + + empty_coverage_report = "" + File.write('sonar-reports/coverage.xml', empty_coverage_report) + end + + private + def reports_folder + logger.info('Deleting and creating directory sonar-reports/') + FileUtils.rm_rf('sonar-reports') + Dir.mkdir('sonar-reports') + end + +end + From 1d909f6e60d171f5e4ff5d29356900221561634a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gae=CC=88l=20Foppolo?= Date: Sun, 1 Sep 2019 14:54:46 +0200 Subject: [PATCH 04/30] Add SonarScanner class --- analyzer/sonar_scanner.rb | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 analyzer/sonar_scanner.rb diff --git a/analyzer/sonar_scanner.rb b/analyzer/sonar_scanner.rb new file mode 100644 index 00000000..ccc498b8 --- /dev/null +++ b/analyzer/sonar_scanner.rb @@ -0,0 +1,19 @@ +require_relative 'tool' + +class SonarScanner < Tool + def self.command + 'sonar-scannerr' + end + + def initialize(options) + super(options) + end + + def run() + logger.info('Running SonarScanner...') + cmd = "#{self.class.command}" + logger.debug("Will run `#{cmd}`") + system(cmd) + end + +end \ No newline at end of file From 7b9c5eb1056be2277ba15d05284fd70b873553ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gae=CC=88l=20Foppolo?= Date: Sun, 1 Sep 2019 14:55:05 +0200 Subject: [PATCH 05/30] Move main to Analyzer class --- analyzer/analyzer.rb | 71 +++++++++++++++++++++++++++++++++++++++++++ analyzer/main.rb | 60 ------------------------------------ analyzer/swiftlint.rb | 2 +- 3 files changed, 72 insertions(+), 61 deletions(-) create mode 100644 analyzer/analyzer.rb delete mode 100644 analyzer/main.rb diff --git a/analyzer/analyzer.rb b/analyzer/analyzer.rb new file mode 100644 index 00000000..9dce897d --- /dev/null +++ b/analyzer/analyzer.rb @@ -0,0 +1,71 @@ +#!/usr/bin/env ruby +require 'ostruct' +require_relative 'logging' +require_relative 'swiftlint' +require_relative 'sonar_scanner' +require_relative 'options' +require_relative 'properties_reader' +require_relative 'helper' + +# Entry point of the script. +# +# It reads the configurations, run all analytic tools and send reports +# to Sonar. +class Analyzer + include Logging + + def initialize + @options = OpenStruct.new + # list of tools by default + @options.tools = [SwiftLint] + # reporter by default + @options.reporter = SonarScanner + # upload results to SonarQube by default + @options.upload = true + # upload results to SonarQube by default + @options.path = 'sonar-project.properties' + + @helper = Helper.new + + end + + def run + + # read CLI arguments and update configuration + Options.new.parse(ARGV, @options) + + # Initiate reports + @helper.bootstrap_reports + + # Read Sonar project properties + @properties = SonarPropertiesReader.new(@options.path).read + + tools + # reporter + + end + + private + def tools + # Filter tools by availability + @options.tools = @helper.available(@options.tools) + + # Run tools + @options.tools.each do |tool| + tool.new(@properties).run + end + end + + private + def reporter + # Filter reporters by availability + @options.reporter = @helper.available(@options.reporter) + + # Send reports + @options.reporter.new([]).run unless @options.reporter.nil? + + end + +end + +Analyzer.new.run \ No newline at end of file diff --git a/analyzer/main.rb b/analyzer/main.rb deleted file mode 100644 index a73566bf..00000000 --- a/analyzer/main.rb +++ /dev/null @@ -1,60 +0,0 @@ -#!/usr/bin/env ruby -require 'ostruct' -require_relative 'logging' -require_relative 'swiftlint' -require_relative 'options' -require_relative 'properties_reader' - -# Entry point of the script. -# -# It reads the configurations, run all analytic tools and send reports -# to Sonar. -class RunSonarSwift - include Logging - - def run - options = OpenStruct.new - # list of tools by default - options.tools = [SwiftLint] - # upload results to SonarQube by default - options.upload = true - # upload results to SonarQube by default - options.path = 'sonar-project.properties' - - # read CLI arguments and update configuration - Options.new.parse(ARGV, options) - - # Read properties - properties = SonarPropertiesReader.new(options.path).read - - # Initiate reports - # TODO - - # Filter tools by availability - options.tools = available_tools(options.tools) - - # Run tools - options.tools.each do |tool| - tool.new(properties).run - end - - # Send reports - # TODO - - end - - # Check each tool is available and return an updated list of tool. - def available_tools(tools) - tools.select do |tool| - if tool.availability - true - else - logger.warn("#{tool.command} is not found in PATH and won't be available in reports.") - false - end - end - end - -end - -RunSonarSwift.new.run diff --git a/analyzer/swiftlint.rb b/analyzer/swiftlint.rb index dee9a79f..b3f3050c 100644 --- a/analyzer/swiftlint.rb +++ b/analyzer/swiftlint.rb @@ -22,7 +22,7 @@ def run() @sources.each do |source| report_name = "#{source.tr(' ', '_')}-swiftlint.txt" cmd = "#{self.class.command} lint --path #{source} > sonar-reports/#{report_name}" - logger.info("Will run `#{cmd}`") + logger.debug("Will run `#{cmd}`") system(cmd) end end From 6bf4ca55625ffe8f44f6f2373fcaf293409dac70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gae=CC=88l=20Foppolo?= Date: Sun, 1 Sep 2019 15:23:35 +0200 Subject: [PATCH 06/30] Move tools to folder and add Lizard --- analyzer/analyzer.rb | 7 +++--- analyzer/tools/lizard.rb | 32 +++++++++++++++++++++++++++ analyzer/{ => tools}/sonar_scanner.rb | 4 ++-- analyzer/{ => tools}/swiftlint.rb | 6 ++--- analyzer/{ => tools}/tool.rb | 4 ++-- 5 files changed, 43 insertions(+), 10 deletions(-) create mode 100644 analyzer/tools/lizard.rb rename analyzer/{ => tools}/sonar_scanner.rb (77%) rename analyzer/{ => tools}/swiftlint.rb (75%) rename analyzer/{ => tools}/tool.rb (86%) diff --git a/analyzer/analyzer.rb b/analyzer/analyzer.rb index 9dce897d..68ef8f2c 100644 --- a/analyzer/analyzer.rb +++ b/analyzer/analyzer.rb @@ -1,8 +1,9 @@ #!/usr/bin/env ruby require 'ostruct' require_relative 'logging' -require_relative 'swiftlint' -require_relative 'sonar_scanner' +require_relative 'tools/swiftlint' +require_relative 'tools/lizard' +require_relative 'tools/sonar_scanner' require_relative 'options' require_relative 'properties_reader' require_relative 'helper' @@ -17,7 +18,7 @@ class Analyzer def initialize @options = OpenStruct.new # list of tools by default - @options.tools = [SwiftLint] + @options.tools = [SwiftLint, Lizard] # reporter by default @options.reporter = SonarScanner # upload results to SonarQube by default diff --git a/analyzer/tools/lizard.rb b/analyzer/tools/lizard.rb new file mode 100644 index 00000000..ab2a78d0 --- /dev/null +++ b/analyzer/tools/lizard.rb @@ -0,0 +1,32 @@ +require_relative 'tool' + +# Lizard computes the code complexity. +# +# @see http://www.lizard.ws +class Lizard < Tool + def self.command + 'lizard' + end + + def initialize(options) + @sources = options[:sources] + super(options) + end + + def run() + logger.info('Running...') + cmd = "#{self.class.command} --xml" + @sources.each do |source| + cmd += " \"#{source}\"" + end + cmd += " > sonar-reports/lizard-reports.xml" + logger.debug("Will run `#{cmd}`") + system(cmd) + end + + private + + def validate_settings! + fatal_error('Sources must be set.') if @sources.nil? + end +end \ No newline at end of file diff --git a/analyzer/sonar_scanner.rb b/analyzer/tools/sonar_scanner.rb similarity index 77% rename from analyzer/sonar_scanner.rb rename to analyzer/tools/sonar_scanner.rb index ccc498b8..9227dd49 100644 --- a/analyzer/sonar_scanner.rb +++ b/analyzer/tools/sonar_scanner.rb @@ -2,7 +2,7 @@ class SonarScanner < Tool def self.command - 'sonar-scannerr' + 'sonar-scanner' end def initialize(options) @@ -10,7 +10,7 @@ def initialize(options) end def run() - logger.info('Running SonarScanner...') + logger.info('Running...') cmd = "#{self.class.command}" logger.debug("Will run `#{cmd}`") system(cmd) diff --git a/analyzer/swiftlint.rb b/analyzer/tools/swiftlint.rb similarity index 75% rename from analyzer/swiftlint.rb rename to analyzer/tools/swiftlint.rb index b3f3050c..c83ad3fc 100644 --- a/analyzer/swiftlint.rb +++ b/analyzer/tools/swiftlint.rb @@ -18,10 +18,10 @@ def initialize(options) end def run() - logger.info('Running SwiftLint...') + logger.info('Running...') @sources.each do |source| report_name = "#{source.tr(' ', '_')}-swiftlint.txt" - cmd = "#{self.class.command} lint --path #{source} > sonar-reports/#{report_name}" + cmd = "#{self.class.command} lint --path \"#{source}\" > sonar-reports/#{report_name}" logger.debug("Will run `#{cmd}`") system(cmd) end @@ -30,6 +30,6 @@ def run() private def validate_settings! - fatal_error('SwiftLint: Sources must be set.') if @sources.nil? + fatal_error('Sources must be set.') if @sources.nil? end end \ No newline at end of file diff --git a/analyzer/tool.rb b/analyzer/tools/tool.rb similarity index 86% rename from analyzer/tool.rb rename to analyzer/tools/tool.rb index 5a31cc02..20e1f42e 100644 --- a/analyzer/tool.rb +++ b/analyzer/tools/tool.rb @@ -1,5 +1,5 @@ -require_relative 'logging' -require_relative 'canfail' +require_relative '../logging' +require_relative '../canfail' # A base class for tool wrappers. # From 95d7465a57907b4481a846af6d672954bf1195b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gae=CC=88l=20Foppolo?= Date: Sun, 1 Sep 2019 15:26:05 +0200 Subject: [PATCH 07/30] Add SonarRunner class --- analyzer/analyzer.rb | 1 + analyzer/tools/sonar_runner.rb | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 analyzer/tools/sonar_runner.rb diff --git a/analyzer/analyzer.rb b/analyzer/analyzer.rb index 68ef8f2c..50a2320c 100644 --- a/analyzer/analyzer.rb +++ b/analyzer/analyzer.rb @@ -4,6 +4,7 @@ require_relative 'tools/swiftlint' require_relative 'tools/lizard' require_relative 'tools/sonar_scanner' +require_relative 'tools/sonar_runner' require_relative 'options' require_relative 'properties_reader' require_relative 'helper' diff --git a/analyzer/tools/sonar_runner.rb b/analyzer/tools/sonar_runner.rb new file mode 100644 index 00000000..f432e83d --- /dev/null +++ b/analyzer/tools/sonar_runner.rb @@ -0,0 +1,19 @@ +require_relative 'tool' + +class SonarRunner < Tool + def self.command + 'sonar-runner' + end + + def initialize(options) + super(options) + end + + def run() + logger.info('Running...') + cmd = "#{self.class.command}" + logger.debug("Will run `#{cmd}`") + system(cmd) + end + +end \ No newline at end of file From 2640ac0869bb8e1ab0cdf2421d661ff05df45ebb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gae=CC=88l=20Foppolo?= Date: Sun, 1 Sep 2019 17:08:35 +0200 Subject: [PATCH 08/30] Add XCPretty & Slather class --- analyzer/Gemfile | 4 ++- analyzer/Gemfile.lock | 43 ++++++++++++++++++++++++++++++++ analyzer/tools/slather.rb | 51 ++++++++++++++++++++++++++++++++++++++ analyzer/tools/xcpretty.rb | 25 +++++++++++++++++++ 4 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 analyzer/tools/slather.rb create mode 100644 analyzer/tools/xcpretty.rb diff --git a/analyzer/Gemfile b/analyzer/Gemfile index 227da0d1..ada58715 100644 --- a/analyzer/Gemfile +++ b/analyzer/Gemfile @@ -1,3 +1,5 @@ source 'https://rubygems.org' -gem 'java-properties', "= 0.2.0" \ No newline at end of file +gem 'java-properties', "= 0.2.0" +gem 'xcpretty', "= 0.2.2", git: "https://github.com/Backelite/xcpretty" +gem 'slather', "= 2.4.7" \ No newline at end of file diff --git a/analyzer/Gemfile.lock b/analyzer/Gemfile.lock index 7bfecb52..366e94ab 100644 --- a/analyzer/Gemfile.lock +++ b/analyzer/Gemfile.lock @@ -1,13 +1,56 @@ +GIT + remote: https://github.com/Backelite/xcpretty + revision: 70668d61562744b3d22a309b1c49a15805f7fa75 + specs: + xcpretty (0.2.2) + rouge (~> 1.8) + GEM remote: https://rubygems.org/ specs: + CFPropertyList (3.0.1) + activesupport (4.2.11.1) + i18n (~> 0.7) + minitest (~> 5.1) + thread_safe (~> 0.3, >= 0.3.4) + tzinfo (~> 1.1) + atomos (0.1.3) + claide (1.0.3) + clamp (1.3.1) + colored2 (3.1.2) + concurrent-ruby (1.1.5) + i18n (0.9.5) + concurrent-ruby (~> 1.0) java-properties (0.2.0) + mini_portile2 (2.4.0) + minitest (5.11.3) + nanaimo (0.2.6) + nokogiri (1.10.4) + mini_portile2 (~> 2.4.0) + rouge (1.11.1) + slather (2.4.7) + CFPropertyList (>= 2.2, < 4) + activesupport (>= 4.0.2, < 5) + clamp (~> 1.3) + nokogiri (~> 1.8) + xcodeproj (~> 1.7) + thread_safe (0.3.6) + tzinfo (1.2.5) + thread_safe (~> 0.1) + xcodeproj (1.12.0) + CFPropertyList (>= 2.3.3, < 4.0) + atomos (~> 0.1.3) + claide (>= 1.0.2, < 2.0) + colored2 (~> 3.1) + nanaimo (~> 0.2.6) PLATFORMS ruby DEPENDENCIES java-properties (= 0.2.0) + slather (= 2.4.7) + xcpretty (= 0.2.2)! BUNDLED WITH 2.0.2 diff --git a/analyzer/tools/slather.rb b/analyzer/tools/slather.rb new file mode 100644 index 00000000..bca5011c --- /dev/null +++ b/analyzer/tools/slather.rb @@ -0,0 +1,51 @@ +require 'fileutils' +require_relative 'tool' + +class Slather < Tool + def self.command + 'slather' + end + + def initialize(options) + @workspace = options[:workspace] + @project = options[:project] + @scheme = options[:scheme] + @exclude_from_coverage = options[:exclude_from_coverage] + @binary_names = options[:binary_names] + super(options) + end + + def run() + logger.info('Running...') + + cmd = "#{self.class.command} coverage" + unless @binary_names.nil? + @binary_names.each do |binary| + cmd += " --binary-basename \"#{binary}\"" + end + end + unless @exclude_from_coverage.nil? + @exclude_from_coverage.each do |exclusion| + cmd += " -i \"#{exclusion}\"" + end + end + cmd += " --input-format profdata --cobertura-xml --output-directory sonar-reports" + cmd += " --workspace #{@workspace}" unless @workspace.nil? + cmd += " --scheme #{@scheme} #{@project}" + logger.debug("Will run `#{cmd}`") + system(cmd) + + FileUtils.mv('sonar-reports/cobertura.xml', 'sonar-reports/coverage-swift.xml') + + end + + private + + def validate_settings! + # @workspace is optional + fatal_error('A project must be set in order to compute coverage') if @project.nil? + fatal_error('A scheme must be set in order to compute coverage') if @scheme.nil? + # @exclude_from_coverage is optional + # @binary_names is optional + end +end \ No newline at end of file diff --git a/analyzer/tools/xcpretty.rb b/analyzer/tools/xcpretty.rb new file mode 100644 index 00000000..6e375ee2 --- /dev/null +++ b/analyzer/tools/xcpretty.rb @@ -0,0 +1,25 @@ +require 'fileutils' +require_relative 'tool' + +class XCPretty < Tool + def self.command + 'oclint-json-compilation-database' + end + + def initialize(options) + super(options) + end + + def run() + logger.info('Running...') + cmd = "cat sonar-reports/xcodebuild.log" + cmd += " | #{self.class.command} -t --report junit -o sonar-reports/TEST-report.xml" + logger.debug("Will run `#{cmd}`") + system(cmd) + end + + private + + def validate_settings! + end +end \ No newline at end of file From 0a831caf86a5b8707a06ab6c0e3bebc839749bd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gae=CC=88l=20Foppolo?= Date: Sun, 1 Sep 2019 17:09:02 +0200 Subject: [PATCH 09/30] Add UnitTests & OCLint class --- analyzer/tools/oclint.rb | 42 ++++++++++++++++++++++++++++++++++ analyzer/tools/unit_tests.rb | 44 ++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 analyzer/tools/oclint.rb create mode 100644 analyzer/tools/unit_tests.rb diff --git a/analyzer/tools/oclint.rb b/analyzer/tools/oclint.rb new file mode 100644 index 00000000..314a915e --- /dev/null +++ b/analyzer/tools/oclint.rb @@ -0,0 +1,42 @@ +require_relative 'tool' +require 'fileutils' + +class OCLint < Tool + + MAX_PRIORITY = 10000 + LONG_LINE_THRESHOLD = 250 + + def self.command + 'oclint-json-compilation-database' + end + + def initialize(options) + @sources = options[:sources] + super(options) + end + + def run() + logger.info('Running...') + @sources.each do |source| + report_name = "#{source.tr(' ', '_')}-oclint.xml" + + cmd = "#{self.class.command}" + cmd += " --include \"#{source}\"" + cmd += " -- -rc LONG_LINE=#{LONG_LINE_THRESHOLD}" + cmd += " -max-priority-1 #{MAX_PRIORITY} -max-priority-2 #{MAX_PRIORITY} -max-priority-3 #{MAX_PRIORITY}" + cmd += " -report-type pmd" + cmd += " -o sonar-reports/#{report_name}" + + logger.debug("Will run `#{cmd}`") + system(cmd) + end + + end + + private + + def validate_settings! + fatal_error('Sources must be set in order to lint') if @sources.nil? + fatal_error("compile_commands.json not found") unless File.exist?("compile_commands.json") + end +end \ No newline at end of file diff --git a/analyzer/tools/unit_tests.rb b/analyzer/tools/unit_tests.rb new file mode 100644 index 00000000..e003f3f2 --- /dev/null +++ b/analyzer/tools/unit_tests.rb @@ -0,0 +1,44 @@ +require_relative 'tool' + +# Runs unit tests using Xcode with `xcodebuild` +class UnitTests < Tool + def self.command + 'xcodebuild' + end + + def initialize(options) + @workspace = options[:workspace] + @project = options[:project] + @scheme = options[:scheme] + @configuration = options[:configuration] + @simulator = options[:simulator] + @exclude_from_coverage = options[:exclude_from_coverage] + super(options) + end + + def run + logger.info('Running ...') + cmd = "#{self.class.command} clean build-for-testing test" + cmd += " -workspace \"#{@workspace}\"" unless @workspace.nil? + cmd += " -project \"#{@project}\"" unless !@workspace.nil? + cmd += " -scheme \"#{@scheme}\"" + cmd += " -configuration \"#{@configuration}\"" + cmd += " -enableCodeCoverage YES" + cmd += " -destination '#{@simulator}' -destination-timeout 60" unless @simulator.nil? + cmd += " | tee sonar-reports/xcodebuild.log" + logger.debug("Will run `#{cmd}`") + system(cmd) + end + + private + + def validate_settings! + # @workspace is optional + fatal_error('A project must be set in order to compute coverage') if @project.nil? + fatal_error('A scheme must be set in order to build and test the app') if @scheme.nil? + fatal_error('A configuration must be set in order to build and test the app') if @configuration.nil? + logger.warn('No simulator specified') if @simulator.nil? + # @exclude_from_coverage is optional + end + +end \ No newline at end of file From 17a0fa1bf95751c8f827308eeeefb7a89b3c1d55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gae=CC=88l=20Foppolo?= Date: Sun, 1 Sep 2019 17:09:16 +0200 Subject: [PATCH 10/30] Update error messages --- analyzer/tools/lizard.rb | 2 +- analyzer/tools/swiftlint.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/analyzer/tools/lizard.rb b/analyzer/tools/lizard.rb index ab2a78d0..050f4278 100644 --- a/analyzer/tools/lizard.rb +++ b/analyzer/tools/lizard.rb @@ -27,6 +27,6 @@ def run() private def validate_settings! - fatal_error('Sources must be set.') if @sources.nil? + fatal_error('Sources must be set in order to compute complexity') if @sources.nil? end end \ No newline at end of file diff --git a/analyzer/tools/swiftlint.rb b/analyzer/tools/swiftlint.rb index c83ad3fc..7470ad3a 100644 --- a/analyzer/tools/swiftlint.rb +++ b/analyzer/tools/swiftlint.rb @@ -30,6 +30,6 @@ def run() private def validate_settings! - fatal_error('Sources must be set.') if @sources.nil? + fatal_error('Sources must be set in order to lint') if @sources.nil? end end \ No newline at end of file From 10573968fa0a0ed66cc0e321d2b7c15849ea3dc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gae=CC=88l=20Foppolo?= Date: Sun, 1 Sep 2019 17:09:47 +0200 Subject: [PATCH 11/30] Add more check when parsing project properties, early exit --- analyzer/properties_reader.rb | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/analyzer/properties_reader.rb b/analyzer/properties_reader.rb index 359ce229..68a5278e 100644 --- a/analyzer/properties_reader.rb +++ b/analyzer/properties_reader.rb @@ -29,22 +29,38 @@ def read_properties(properties) options = {} options[:project] = properties[:'sonar.swift.project'] options[:workspace] = properties[:'sonar.swift.workspace'] - options[:sources] = properties[:'sonar.sources'].split(',') + options[:sources] = properties[:'sonar.sources'] + options[:sources] = options[:'sonar.sources'].split(',') unless options[:'sonar.sources'].nil? options[:scheme] = properties[:'sonar.swift.appScheme'] options[:configuration] = properties[:'sonar.swift.appConfiguration'] options[:simulator] = properties[:'sonar.swift.simulator'] - options[:exclude_from_coverage] = properties[:'sonar.swift.excludedPathsFromCoverage'].split(',') + options[:exclude_from_coverage] = properties[:'sonar.swift.excludedPathsFromCoverage'] + options[:exclude_from_coverage] = options[:exclude_from_coverage].split(',') unless options[:exclude_from_coverage].nil? + options[:binary_names] = properties[:'sonar.coverage.binaryNames'] + options[:binary_names] = options[:binary_names].split(',') unless options[:binary_names].nil? options end def validate_settings!(options) - fatal_error('No project or workspace specified.') if (options[:workspace].nil? && options[:project].nil?) - fatal_error('No sources folder specified.') if options[:sources].nil? - fatal_error('No scheme specified.') if options[:scheme].nil? + fatal_error("No project or workspace specified in #{@file}") if (options[:workspace].nil? && options[:project].nil?) + check_file(options[:workspace]) + check_file(options[:project]) + fatal_error("No sources folder specified in #{@file}") if options[:sources].nil? + options[:sources].each do |source| + check_file(source) + end + fatal_error("No scheme specified in #{@file}") if options[:scheme].nil? if options[:configuration].nil? logger.warn('No build configuration set, defaulting to Debug') options[:configuration] = 'Debug' end options end + + def check_file(file) + unless file.nil? + # fatal_error("#{file} not found") unless File.exist?("file") + end + end + end \ No newline at end of file From b31193862bf0a7ccbc4dd1461d7f8d199d25248a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gae=CC=88l=20Foppolo?= Date: Sun, 1 Sep 2019 17:10:26 +0200 Subject: [PATCH 12/30] Add new tools in Analyzer --- analyzer/analyzer.rb | 6 +++++- analyzer/properties_reader.rb | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/analyzer/analyzer.rb b/analyzer/analyzer.rb index 50a2320c..9af13576 100644 --- a/analyzer/analyzer.rb +++ b/analyzer/analyzer.rb @@ -5,6 +5,10 @@ require_relative 'tools/lizard' require_relative 'tools/sonar_scanner' require_relative 'tools/sonar_runner' +require_relative 'tools/unit_tests' +require_relative 'tools/xcpretty' +require_relative 'tools/slather' +require_relative 'tools/oclint' require_relative 'options' require_relative 'properties_reader' require_relative 'helper' @@ -19,7 +23,7 @@ class Analyzer def initialize @options = OpenStruct.new # list of tools by default - @options.tools = [SwiftLint, Lizard] + @options.tools = [UnitTests, XCPretty, Slather, SwiftLint, Lizard, OCLint] # reporter by default @options.reporter = SonarScanner # upload results to SonarQube by default diff --git a/analyzer/properties_reader.rb b/analyzer/properties_reader.rb index 68a5278e..f129845e 100644 --- a/analyzer/properties_reader.rb +++ b/analyzer/properties_reader.rb @@ -59,7 +59,7 @@ def validate_settings!(options) def check_file(file) unless file.nil? - # fatal_error("#{file} not found") unless File.exist?("file") + fatal_error("#{file} not found") unless File.exist?("file") end end From 92f3d1d6eb99e9f7bc53e26a31f504a4e162db1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gae=CC=88l=20Foppolo?= Date: Sun, 1 Sep 2019 17:20:51 +0200 Subject: [PATCH 13/30] Add FauxPas class --- analyzer/analyzer.rb | 3 ++- analyzer/tools/fauxpas.rb | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 analyzer/tools/fauxpas.rb diff --git a/analyzer/analyzer.rb b/analyzer/analyzer.rb index 9af13576..608e17d2 100644 --- a/analyzer/analyzer.rb +++ b/analyzer/analyzer.rb @@ -9,6 +9,7 @@ require_relative 'tools/xcpretty' require_relative 'tools/slather' require_relative 'tools/oclint' +require_relative 'tools/fauxpas' require_relative 'options' require_relative 'properties_reader' require_relative 'helper' @@ -23,7 +24,7 @@ class Analyzer def initialize @options = OpenStruct.new # list of tools by default - @options.tools = [UnitTests, XCPretty, Slather, SwiftLint, Lizard, OCLint] + @options.tools = [UnitTests, XCPretty, Slather, SwiftLint, Lizard, OCLint, FauxPas] # reporter by default @options.reporter = SonarScanner # upload results to SonarQube by default diff --git a/analyzer/tools/fauxpas.rb b/analyzer/tools/fauxpas.rb new file mode 100644 index 00000000..77d90e2b --- /dev/null +++ b/analyzer/tools/fauxpas.rb @@ -0,0 +1,32 @@ +require_relative 'tool' + +class FauxPas < Tool + def self.command + 'fauxpas' + end + + def initialize(options) + @workspace = options[:workspace] + @project = options[:project] + @scheme = options[:scheme] + super(options) + end + + def run() + logger.info('Running...') + cmd = "#{self.class.command} check -o json #{@project}" + cmd += " --workspace #{@workspace}" unless @workspace.nil? + cmd += " --scheme #{@scheme}" + cmd += " > sonar-reports/fauxpas.json" + logger.debug("Will run `#{cmd}`") + system(cmd) + end + + private + + def validate_settings! + # @workspace is optional + fatal_error('A project must be set in order to compute coverage') if @project.nil? + fatal_error('A scheme must be set in order to compute coverage') if @scheme.nil? + end +end \ No newline at end of file From 94c31fc4732a5a61d404de3e545616cea3d8f78d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gae=CC=88l=20Foppolo?= Date: Sun, 1 Sep 2019 17:21:18 +0200 Subject: [PATCH 14/30] Fix Hash key name --- analyzer/properties_reader.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/analyzer/properties_reader.rb b/analyzer/properties_reader.rb index f129845e..983aaf58 100644 --- a/analyzer/properties_reader.rb +++ b/analyzer/properties_reader.rb @@ -30,7 +30,7 @@ def read_properties(properties) options[:project] = properties[:'sonar.swift.project'] options[:workspace] = properties[:'sonar.swift.workspace'] options[:sources] = properties[:'sonar.sources'] - options[:sources] = options[:'sonar.sources'].split(',') unless options[:'sonar.sources'].nil? + options[:sources] = options[:sources].split(',') unless options[:sources].nil? options[:scheme] = properties[:'sonar.swift.appScheme'] options[:configuration] = properties[:'sonar.swift.appConfiguration'] options[:simulator] = properties[:'sonar.swift.simulator'] From 41bca6163ba2057081f2f3ddbafdb054b7a44333 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gae=CC=88l=20Foppolo?= Date: Sun, 1 Sep 2019 18:05:18 +0200 Subject: [PATCH 15/30] Rework Tool to make it support list of commands --- analyzer/analyzer.rb | 23 +++++---- analyzer/helper.rb | 13 +++-- analyzer/tools/fauxpas.rb | 58 +++++++++++----------- analyzer/tools/lizard.rb | 52 ++++++++++---------- analyzer/tools/oclint.rb | 14 +++--- analyzer/tools/slather.rb | 86 +++++++++++++++++---------------- analyzer/tools/sonar_runner.rb | 32 ++++++------ analyzer/tools/sonar_scanner.rb | 32 ++++++------ analyzer/tools/swiftlint.rb | 50 ++++++++++--------- analyzer/tools/tool.rb | 38 +++++++-------- analyzer/tools/unit_tests.rb | 82 ++++++++++++++++--------------- analyzer/tools/xcpretty.rb | 25 ---------- 12 files changed, 246 insertions(+), 259 deletions(-) delete mode 100644 analyzer/tools/xcpretty.rb diff --git a/analyzer/analyzer.rb b/analyzer/analyzer.rb index 608e17d2..ac07ac35 100644 --- a/analyzer/analyzer.rb +++ b/analyzer/analyzer.rb @@ -6,7 +6,6 @@ require_relative 'tools/sonar_scanner' require_relative 'tools/sonar_runner' require_relative 'tools/unit_tests' -require_relative 'tools/xcpretty' require_relative 'tools/slather' require_relative 'tools/oclint' require_relative 'tools/fauxpas' @@ -20,18 +19,18 @@ # to Sonar. class Analyzer include Logging - + def initialize @options = OpenStruct.new # list of tools by default - @options.tools = [UnitTests, XCPretty, Slather, SwiftLint, Lizard, OCLint, FauxPas] + @options.tools = [UnitTests, Slather, SwiftLint, Lizard, OCLint, FauxPas] # reporter by default @options.reporter = SonarScanner # upload results to SonarQube by default @options.upload = true # upload results to SonarQube by default @options.path = 'sonar-project.properties' - + @helper = Helper.new end @@ -40,18 +39,18 @@ def run # read CLI arguments and update configuration Options.new.parse(ARGV, @options) - + # Initiate reports @helper.bootstrap_reports - + # Read Sonar project properties - @properties = SonarPropertiesReader.new(@options.path).read - + @properties = SonarPropertiesReader.new(@options.path).read + tools # reporter - + end - + private def tools # Filter tools by availability @@ -62,7 +61,7 @@ def tools tool.new(@properties).run end end - + private def reporter # Filter reporters by availability @@ -70,7 +69,7 @@ def reporter # Send reports @options.reporter.new([]).run unless @options.reporter.nil? - + end end diff --git a/analyzer/helper.rb b/analyzer/helper.rb index 4aeb05bb..d12dc5a7 100644 --- a/analyzer/helper.rb +++ b/analyzer/helper.rb @@ -17,7 +17,7 @@ def available(programs) case programs when Array programs.select do |program| - _available(program) unless nil + _available(program) end else _available(programs) @@ -27,12 +27,11 @@ def available(programs) # Check program is available and return an updated list. private def _available(program) - if program.availability - program - else - logger.warn("#{program.command} is not found in PATH.") - nil - end + program.command.values.reduce(true) { |available, tool| + toolAvailable = system("which #{tool} 2>&1 > /dev/null") + logger.warn("#{tool} is not found in PATH.") if !toolAvailable + available &= toolAvailable + } end private diff --git a/analyzer/tools/fauxpas.rb b/analyzer/tools/fauxpas.rb index 77d90e2b..eddb12f7 100644 --- a/analyzer/tools/fauxpas.rb +++ b/analyzer/tools/fauxpas.rb @@ -1,32 +1,34 @@ require_relative 'tool' class FauxPas < Tool - def self.command - 'fauxpas' - end - - def initialize(options) - @workspace = options[:workspace] - @project = options[:project] - @scheme = options[:scheme] - super(options) - end - - def run() - logger.info('Running...') - cmd = "#{self.class.command} check -o json #{@project}" - cmd += " --workspace #{@workspace}" unless @workspace.nil? - cmd += " --scheme #{@scheme}" - cmd += " > sonar-reports/fauxpas.json" - logger.debug("Will run `#{cmd}`") - system(cmd) - end - - private - - def validate_settings! - # @workspace is optional - fatal_error('A project must be set in order to compute coverage') if @project.nil? - fatal_error('A scheme must be set in order to compute coverage') if @scheme.nil? - end + def self.command + { + fauxpas: 'fauxpas' + } + end + + def initialize(options) + @workspace = options[:workspace] + @project = options[:project] + @scheme = options[:scheme] + super(options) + end + + def run() + logger.info('Running...') + cmd = "#{self.class.command[:fauxpas]} check -o json #{@project}" + cmd += " --workspace #{@workspace}" unless @workspace.nil? + cmd += " --scheme #{@scheme}" + cmd += " > sonar-reports/fauxpas.json" + logger.debug("Will run `#{cmd}`") + system(cmd) + end + + private + + def validate_settings! + # @workspace is optional + fatal_error('A project must be set in order to compute coverage') if @project.nil? + fatal_error('A scheme must be set in order to compute coverage') if @scheme.nil? + end end \ No newline at end of file diff --git a/analyzer/tools/lizard.rb b/analyzer/tools/lizard.rb index 050f4278..938a8067 100644 --- a/analyzer/tools/lizard.rb +++ b/analyzer/tools/lizard.rb @@ -4,29 +4,31 @@ # # @see http://www.lizard.ws class Lizard < Tool - def self.command - 'lizard' - end - - def initialize(options) - @sources = options[:sources] - super(options) - end - - def run() - logger.info('Running...') - cmd = "#{self.class.command} --xml" - @sources.each do |source| - cmd += " \"#{source}\"" - end - cmd += " > sonar-reports/lizard-reports.xml" - logger.debug("Will run `#{cmd}`") - system(cmd) - end - - private - - def validate_settings! - fatal_error('Sources must be set in order to compute complexity') if @sources.nil? - end + def self.command + { + lizard: 'lizard' + } + end + + def initialize(options) + @sources = options[:sources] + super(options) + end + + def run() + logger.info('Running...') + cmd = "#{self.class.command[:lizard]} --xml" + @sources.each do |source| + cmd += " \"#{source}\"" + end + cmd += " > sonar-reports/lizard-reports.xml" + logger.debug("Will run `#{cmd}`") + system(cmd) + end + + private + + def validate_settings! + fatal_error('Sources must be set in order to compute complexity') if @sources.nil? + end end \ No newline at end of file diff --git a/analyzer/tools/oclint.rb b/analyzer/tools/oclint.rb index 314a915e..87cfbdca 100644 --- a/analyzer/tools/oclint.rb +++ b/analyzer/tools/oclint.rb @@ -4,10 +4,12 @@ class OCLint < Tool MAX_PRIORITY = 10000 - LONG_LINE_THRESHOLD = 250 + LONG_LINE_THRESHOLD = 250 def self.command - 'oclint-json-compilation-database' + { + oclint: 'oclint-json-compilation-database' + } end def initialize(options) @@ -19,18 +21,18 @@ def run() logger.info('Running...') @sources.each do |source| report_name = "#{source.tr(' ', '_')}-oclint.xml" - - cmd = "#{self.class.command}" + + cmd = "#{self.class.command[:oclint]}" cmd += " --include \"#{source}\"" cmd += " -- -rc LONG_LINE=#{LONG_LINE_THRESHOLD}" cmd += " -max-priority-1 #{MAX_PRIORITY} -max-priority-2 #{MAX_PRIORITY} -max-priority-3 #{MAX_PRIORITY}" cmd += " -report-type pmd" cmd += " -o sonar-reports/#{report_name}" - + logger.debug("Will run `#{cmd}`") system(cmd) end - + end private diff --git a/analyzer/tools/slather.rb b/analyzer/tools/slather.rb index bca5011c..c1b514d4 100644 --- a/analyzer/tools/slather.rb +++ b/analyzer/tools/slather.rb @@ -2,50 +2,52 @@ require_relative 'tool' class Slather < Tool - def self.command - 'slather' - end - - def initialize(options) - @workspace = options[:workspace] - @project = options[:project] - @scheme = options[:scheme] - @exclude_from_coverage = options[:exclude_from_coverage] - @binary_names = options[:binary_names] - super(options) - end - - def run() - logger.info('Running...') + def self.command + { + slather: 'slather' + } + end - cmd = "#{self.class.command} coverage" - unless @binary_names.nil? - @binary_names.each do |binary| - cmd += " --binary-basename \"#{binary}\"" - end + def initialize(options) + @workspace = options[:workspace] + @project = options[:project] + @scheme = options[:scheme] + @exclude_from_coverage = options[:exclude_from_coverage] + @binary_names = options[:binary_names] + super(options) end - unless @exclude_from_coverage.nil? - @exclude_from_coverage.each do |exclusion| - cmd += " -i \"#{exclusion}\"" + + def run() + logger.info('Running...') + + cmd = "#{self.class.command[:slather]} coverage" + unless @binary_names.nil? + @binary_names.each do |binary| + cmd += " --binary-basename \"#{binary}\"" + end + end + unless @exclude_from_coverage.nil? + @exclude_from_coverage.each do |exclusion| + cmd += " -i \"#{exclusion}\"" + end end + cmd += " --input-format profdata --cobertura-xml --output-directory sonar-reports" + cmd += " --workspace #{@workspace}" unless @workspace.nil? + cmd += " --scheme #{@scheme} #{@project}" + logger.debug("Will run `#{cmd}`") + system(cmd) + + FileUtils.mv('sonar-reports/cobertura.xml', 'sonar-reports/coverage-swift.xml') + + end + + private + + def validate_settings! + # @workspace is optional + fatal_error('A project must be set in order to compute coverage') if @project.nil? + fatal_error('A scheme must be set in order to compute coverage') if @scheme.nil? + # @exclude_from_coverage is optional + # @binary_names is optional end - cmd += " --input-format profdata --cobertura-xml --output-directory sonar-reports" - cmd += " --workspace #{@workspace}" unless @workspace.nil? - cmd += " --scheme #{@scheme} #{@project}" - logger.debug("Will run `#{cmd}`") - system(cmd) - - FileUtils.mv('sonar-reports/cobertura.xml', 'sonar-reports/coverage-swift.xml') - - end - - private - - def validate_settings! - # @workspace is optional - fatal_error('A project must be set in order to compute coverage') if @project.nil? - fatal_error('A scheme must be set in order to compute coverage') if @scheme.nil? - # @exclude_from_coverage is optional - # @binary_names is optional - end end \ No newline at end of file diff --git a/analyzer/tools/sonar_runner.rb b/analyzer/tools/sonar_runner.rb index f432e83d..89990cab 100644 --- a/analyzer/tools/sonar_runner.rb +++ b/analyzer/tools/sonar_runner.rb @@ -1,19 +1,21 @@ require_relative 'tool' class SonarRunner < Tool - def self.command - 'sonar-runner' - end - - def initialize(options) - super(options) - end - - def run() - logger.info('Running...') - cmd = "#{self.class.command}" - logger.debug("Will run `#{cmd}`") - system(cmd) - end - + def self.command + { + :runner: 'sonar-runner' + } + end + + def initialize(options) + super(options) + end + + def run() + logger.info('Running...') + cmd = "#{self.class.command[:runner]}" + logger.debug("Will run `#{cmd}`") + system(cmd) + end + end \ No newline at end of file diff --git a/analyzer/tools/sonar_scanner.rb b/analyzer/tools/sonar_scanner.rb index 9227dd49..56115360 100644 --- a/analyzer/tools/sonar_scanner.rb +++ b/analyzer/tools/sonar_scanner.rb @@ -1,19 +1,21 @@ require_relative 'tool' class SonarScanner < Tool - def self.command - 'sonar-scanner' - end - - def initialize(options) - super(options) - end - - def run() - logger.info('Running...') - cmd = "#{self.class.command}" - logger.debug("Will run `#{cmd}`") - system(cmd) - end - + def self.command + { + :scanner: 'sonar-scanner' + } + end + + def initialize(options) + super(options) + end + + def run() + logger.info('Running...') + cmd = "#{self.class.command[:scanner]}" + logger.debug("Will run `#{cmd}`") + system(cmd) + end + end \ No newline at end of file diff --git a/analyzer/tools/swiftlint.rb b/analyzer/tools/swiftlint.rb index 7470ad3a..e5c1a335 100644 --- a/analyzer/tools/swiftlint.rb +++ b/analyzer/tools/swiftlint.rb @@ -8,28 +8,30 @@ # # https://github.com/realm/SwiftLint class SwiftLint < Tool - def self.command - 'swiftlint' - end - - def initialize(options) - @sources = options[:sources] - super(options) - end - - def run() - logger.info('Running...') - @sources.each do |source| - report_name = "#{source.tr(' ', '_')}-swiftlint.txt" - cmd = "#{self.class.command} lint --path \"#{source}\" > sonar-reports/#{report_name}" - logger.debug("Will run `#{cmd}`") - system(cmd) - end - end - - private - - def validate_settings! - fatal_error('Sources must be set in order to lint') if @sources.nil? - end + def self.command + { + :swiftlint: 'swiftlint' + } + end + + def initialize(options) + @sources = options[:sources] + super(options) + end + + def run() + logger.info('Running...') + @sources.each do |source| + report_name = "#{source.tr(' ', '_')}-swiftlint.txt" + cmd = "#{self.class.command[:swiftlint]} lint --path \"#{source}\" > sonar-reports/#{report_name}" + logger.debug("Will run `#{cmd}`") + system(cmd) + end + end + + private + + def validate_settings! + fatal_error('Sources must be set in order to lint') if @sources.nil? + end end \ No newline at end of file diff --git a/analyzer/tools/tool.rb b/analyzer/tools/tool.rb index 20e1f42e..60c56797 100644 --- a/analyzer/tools/tool.rb +++ b/analyzer/tools/tool.rb @@ -5,25 +5,21 @@ # # Mainly defines a common interface + includes some useful modules. class Tool - include Logging - include CanFail - - def self.command - end - - def initialize(_options) - validate_settings! - end - - def run - end - - protected - def self.availability - system("which #{self.command} 2>&1 > /dev/null") - end - - protected - def validate_settings! - end + include Logging + include CanFail + + def self.command + end + + def initialize(_options) + validate_settings! + end + + def run + end + + protected + + def validate_settings! + end end \ No newline at end of file diff --git a/analyzer/tools/unit_tests.rb b/analyzer/tools/unit_tests.rb index e003f3f2..2a3e720a 100644 --- a/analyzer/tools/unit_tests.rb +++ b/analyzer/tools/unit_tests.rb @@ -2,43 +2,47 @@ # Runs unit tests using Xcode with `xcodebuild` class UnitTests < Tool - def self.command - 'xcodebuild' - end - - def initialize(options) - @workspace = options[:workspace] - @project = options[:project] - @scheme = options[:scheme] - @configuration = options[:configuration] - @simulator = options[:simulator] - @exclude_from_coverage = options[:exclude_from_coverage] - super(options) - end - - def run - logger.info('Running ...') - cmd = "#{self.class.command} clean build-for-testing test" - cmd += " -workspace \"#{@workspace}\"" unless @workspace.nil? - cmd += " -project \"#{@project}\"" unless !@workspace.nil? - cmd += " -scheme \"#{@scheme}\"" - cmd += " -configuration \"#{@configuration}\"" - cmd += " -enableCodeCoverage YES" - cmd += " -destination '#{@simulator}' -destination-timeout 60" unless @simulator.nil? - cmd += " | tee sonar-reports/xcodebuild.log" - logger.debug("Will run `#{cmd}`") - system(cmd) - end - - private - - def validate_settings! - # @workspace is optional - fatal_error('A project must be set in order to compute coverage') if @project.nil? - fatal_error('A scheme must be set in order to build and test the app') if @scheme.nil? - fatal_error('A configuration must be set in order to build and test the app') if @configuration.nil? - logger.warn('No simulator specified') if @simulator.nil? - # @exclude_from_coverage is optional - end - + def self.command + { + xcodebuild: 'xcodebuild', + xcpretty: 'xcpretty' + } + end + + def initialize(options) + @workspace = options[:workspace] + @project = options[:project] + @scheme = options[:scheme] + @configuration = options[:configuration] + @simulator = options[:simulator] + @exclude_from_coverage = options[:exclude_from_coverage] + super(options) + end + + def run + logger.info('Running ...') + cmd = "#{self.class.command[:xcodebuild]} clean build-for-testing test" + cmd += " -workspace \"#{@workspace}\"" unless @workspace.nil? + cmd += " -project \"#{@project}\"" unless !@workspace.nil? + cmd += " -scheme \"#{@scheme}\"" + cmd += " -configuration \"#{@configuration}\"" + cmd += " -enableCodeCoverage YES" + cmd += " -destination '#{@simulator}' -destination-timeout 60" unless @simulator.nil? + cmd += " | tee xcodebuild.log" + cmd += " | #{self.class.command[:xcpretty]} -t --report junit -o sonar-reports/TEST-report.xml" + logger.debug("Will run `#{cmd}`") + system(cmd) + end + + private + + def validate_settings! + # @workspace is optional + fatal_error('A project must be set in order to compute coverage') if @project.nil? + fatal_error('A scheme must be set in order to build and test the app') if @scheme.nil? + fatal_error('A configuration must be set in order to build and test the app') if @configuration.nil? + logger.warn('No simulator specified') if @simulator.nil? + # @exclude_from_coverage is optional + end + end \ No newline at end of file diff --git a/analyzer/tools/xcpretty.rb b/analyzer/tools/xcpretty.rb deleted file mode 100644 index 6e375ee2..00000000 --- a/analyzer/tools/xcpretty.rb +++ /dev/null @@ -1,25 +0,0 @@ -require 'fileutils' -require_relative 'tool' - -class XCPretty < Tool - def self.command - 'oclint-json-compilation-database' - end - - def initialize(options) - super(options) - end - - def run() - logger.info('Running...') - cmd = "cat sonar-reports/xcodebuild.log" - cmd += " | #{self.class.command} -t --report junit -o sonar-reports/TEST-report.xml" - logger.debug("Will run `#{cmd}`") - system(cmd) - end - - private - - def validate_settings! - end -end \ No newline at end of file From 893602745679ca1aea3ed714bc50f52877ee7f8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gae=CC=88l=20Foppolo?= Date: Sun, 1 Sep 2019 18:06:25 +0200 Subject: [PATCH 16/30] Fix hash key --- analyzer/tools/sonar_runner.rb | 2 +- analyzer/tools/sonar_scanner.rb | 2 +- analyzer/tools/swiftlint.rb | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/analyzer/tools/sonar_runner.rb b/analyzer/tools/sonar_runner.rb index 89990cab..c5f8f987 100644 --- a/analyzer/tools/sonar_runner.rb +++ b/analyzer/tools/sonar_runner.rb @@ -3,7 +3,7 @@ class SonarRunner < Tool def self.command { - :runner: 'sonar-runner' + runner: 'sonar-runner' } end diff --git a/analyzer/tools/sonar_scanner.rb b/analyzer/tools/sonar_scanner.rb index 56115360..e52dd228 100644 --- a/analyzer/tools/sonar_scanner.rb +++ b/analyzer/tools/sonar_scanner.rb @@ -3,7 +3,7 @@ class SonarScanner < Tool def self.command { - :scanner: 'sonar-scanner' + scanner: 'sonar-scanner' } end diff --git a/analyzer/tools/swiftlint.rb b/analyzer/tools/swiftlint.rb index e5c1a335..66c8a7ad 100644 --- a/analyzer/tools/swiftlint.rb +++ b/analyzer/tools/swiftlint.rb @@ -10,7 +10,7 @@ class SwiftLint < Tool def self.command { - :swiftlint: 'swiftlint' + swiftlint: 'swiftlint' } end From 2d0431f3e837648ec8069579894e253e22b69905 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gae=CC=88l=20Foppolo?= Date: Sun, 1 Sep 2019 18:18:23 +0200 Subject: [PATCH 17/30] Add JSONCompilationDatabase class --- analyzer/analyzer.rb | 3 +- analyzer/tools/json_compilation_database.rb | 41 +++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 analyzer/tools/json_compilation_database.rb diff --git a/analyzer/analyzer.rb b/analyzer/analyzer.rb index ac07ac35..6a7196b9 100644 --- a/analyzer/analyzer.rb +++ b/analyzer/analyzer.rb @@ -9,6 +9,7 @@ require_relative 'tools/slather' require_relative 'tools/oclint' require_relative 'tools/fauxpas' +require_relative 'tools/json_compilation_database' require_relative 'options' require_relative 'properties_reader' require_relative 'helper' @@ -23,7 +24,7 @@ class Analyzer def initialize @options = OpenStruct.new # list of tools by default - @options.tools = [UnitTests, Slather, SwiftLint, Lizard, OCLint, FauxPas] + @options.tools = [JSONCompilationDatabase, UnitTests, Slather, SwiftLint, Lizard, OCLint, FauxPas] # reporter by default @options.reporter = SonarScanner # upload results to SonarQube by default diff --git a/analyzer/tools/json_compilation_database.rb b/analyzer/tools/json_compilation_database.rb new file mode 100644 index 00000000..9fa9bfa2 --- /dev/null +++ b/analyzer/tools/json_compilation_database.rb @@ -0,0 +1,41 @@ +require_relative 'tool' + +class JSONCompilationDatabase < Tool + def self.command + { + xcodebuild: 'xcodebuild', + xcpretty: 'xcpretty' + } + end + + def initialize(options) + @workspace = options[:workspace] + @project = options[:project] + @scheme = options[:scheme] + @simulator = options[:simulator] + super(options) + end + + def run + logger.info('Running ...') + cmd = "#{self.class.command[:xcodebuild]} clean build" + cmd += " -workspace \"#{@workspace}\"" unless @workspace.nil? + cmd += " -project \"#{@project}\"" unless !@workspace.nil? + cmd += " -scheme \"#{@scheme}\"" + cmd += " -destination '#{@simulator}' -destination-timeout 360 COMPILER_INDEX_STORE_ENABLE=NO" unless @simulator.nil? + cmd += " | tee xcodebuild.log" + cmd += " | #{self.class.command[:xcpretty]} -r json-compilation-database -o compile_commands.json" + logger.debug("Will run `#{cmd}`") + system(cmd) + end + + private + + def validate_settings! + # @workspace is optional + fatal_error('A project must be set in order to compute coverage') if @project.nil? + fatal_error('A scheme must be set in order to build and test the app') if @scheme.nil? + logger.warn('No simulator specified') if @simulator.nil? + end + +end \ No newline at end of file From 881982acc700d88e8e1dce457e9e0865abe5bbc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gae=CC=88l=20Foppolo?= Date: Sun, 1 Sep 2019 18:30:52 +0200 Subject: [PATCH 18/30] Add options to disable tools --- analyzer/options.rb | 122 ++++++++++++++++++++++++++------------------ 1 file changed, 73 insertions(+), 49 deletions(-) diff --git a/analyzer/options.rb b/analyzer/options.rb index d83b62a3..7ad777f0 100644 --- a/analyzer/options.rb +++ b/analyzer/options.rb @@ -1,54 +1,78 @@ require 'optparse' class Options - + REPORTER_ALIASES = { :scanner => "SonarScanner", :runner => "SonarRunner" } - - # - # Return a structure describing the options. - # - def parse(args, options) - # The options specified on the command line will be updated in *options*. - - opt_parser = OptionParser.new do |opts| - opts.banner = "Usage: main.rb [options]" - - opts.separator "" - opts.separator "Specific options:" - - opts.on("-v", "--verbose", "Run verbosely") do |_| - Logging.logger_level = Logger::DEBUG - end - - # Optional - opts.on("--disable-swiftlint", "Disable SwiftLint") do |_| - options.tools.delete_at(options.tools.index(SwiftLint)) - end - - # Optional - opts.on("-p", "--path PATH", String, "Path to properties file.") do |p| - options.path = p - end - - # Optional - opts.on("-r", "--reporter [REPORTER]", REPORTER_ALIASES.keys, + + # + # Return a structure describing the options. + # + def parse(args, options) + # The options specified on the command line will be updated in *options*. + + opt_parser = OptionParser.new do |opts| + opts.banner = "Usage: main.rb [options]" + + opts.separator "" + opts.separator "Specific options:" + + # Optional + opts.on("-p", "--path PATH", String, "Path to Sonar properties file.") do |p| + options.path = p + end + + # Optional + opts.on("-r", "--reporter [REPORTER]", REPORTER_ALIASES.keys, "Select Sonar reporter (scanner, runner)") do |r| - options.reporter = REPORTER_ALIASES[r] - end - - opts.separator "" - opts.separator "Common options:" - - # No argument, shows at tail. This will print an options summary. - # Try it and see! - opts.on_tail("-h", "--help", "Show this message") do - puts opts - exit - end - end - - opt_parser.parse!(args) - - end - -end \ No newline at end of file + options.reporter = REPORTER_ALIASES[r] + end + + opts.separator "" + opts.separator "Disable tools:" + + # Optional + opts.on("--disable-swiftlint", "Disable SwiftLint") do |_| + options.tools.delete_at(options.tools.index(SwiftLint)) + end + + # Optional + opts.on("--disable-oclint", "Disable OCLint") do |_| + options.tools.delete_at(options.tools.index(JSONCompilationDatabase)) + options.tools.delete_at(options.tools.index(OCLint)) + end + + # Optional + opts.on("--disable-slather", "Disable Slather") do |_| + options.tools.delete_at(options.tools.index(Slather)) + end + + # Optional + opts.on("--disable-lizard", "Disable Lizard") do |_| + options.tools.delete_at(options.tools.index(Lizard)) + end + + # Optional + opts.on("--disable-fauxpas", "Disable FauxPas") do |_| + options.tools.delete_at(options.tools.index(FauxPas)) + end + + opts.separator "" + opts.separator "Common options:" + + opts.on("-v", "--verbose", "Run verbosely") do |_| + Logging.logger_level = Logger::DEBUG + end + + # No argument, shows at tail. This will print an options summary. + # Try it and see! + opts.on_tail("-h", "--help", "Show this message") do + puts opts + exit + end + end + + opt_parser.parse!(args) + + end + + end \ No newline at end of file From 7dfb62a4742b4bf11860d48a37a78088716ef0d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gae=CC=88l=20Foppolo?= Date: Sun, 1 Sep 2019 18:35:38 +0200 Subject: [PATCH 19/30] Add option to disable upload (test purpose) --- analyzer/analyzer.rb | 2 +- analyzer/options.rb | 102 ++++++++++++++++++++++--------------------- 2 files changed, 54 insertions(+), 50 deletions(-) diff --git a/analyzer/analyzer.rb b/analyzer/analyzer.rb index 6a7196b9..eb899648 100644 --- a/analyzer/analyzer.rb +++ b/analyzer/analyzer.rb @@ -48,7 +48,7 @@ def run @properties = SonarPropertiesReader.new(@options.path).read tools - # reporter + reporter if upload end diff --git a/analyzer/options.rb b/analyzer/options.rb index 7ad777f0..f1d25e1f 100644 --- a/analyzer/options.rb +++ b/analyzer/options.rb @@ -22,57 +22,61 @@ def parse(args, options) end # Optional - opts.on("-r", "--reporter [REPORTER]", REPORTER_ALIASES.keys, - "Select Sonar reporter (scanner, runner)") do |r| - options.reporter = REPORTER_ALIASES[r] - end - - opts.separator "" - opts.separator "Disable tools:" - - # Optional - opts.on("--disable-swiftlint", "Disable SwiftLint") do |_| - options.tools.delete_at(options.tools.index(SwiftLint)) - end - - # Optional - opts.on("--disable-oclint", "Disable OCLint") do |_| - options.tools.delete_at(options.tools.index(JSONCompilationDatabase)) - options.tools.delete_at(options.tools.index(OCLint)) - end - - # Optional - opts.on("--disable-slather", "Disable Slather") do |_| - options.tools.delete_at(options.tools.index(Slather)) - end - - # Optional - opts.on("--disable-lizard", "Disable Lizard") do |_| - options.tools.delete_at(options.tools.index(Lizard)) - end - - # Optional - opts.on("--disable-fauxpas", "Disable FauxPas") do |_| - options.tools.delete_at(options.tools.index(FauxPas)) - end - - opts.separator "" - opts.separator "Common options:" - - opts.on("-v", "--verbose", "Run verbosely") do |_| - Logging.logger_level = Logger::DEBUG - end - - # No argument, shows at tail. This will print an options summary. - # Try it and see! - opts.on_tail("-h", "--help", "Show this message") do - puts opts - exit - end + opts.on("-r", "--reporter [REPORTER]", REPORTER_ALIASES.keys, "Select Sonar reporter (scanner, runner)") do |r| + options.reporter = REPORTER_ALIASES[r] end - opt_parser.parse!(args) + opts.separator "" + opts.separator "Disable tools:" + + # Optional + opts.on("--disable-swiftlint", "Disable SwiftLint") do |_| + options.tools.delete_at(options.tools.index(SwiftLint)) + end + + # Optional + opts.on("--disable-oclint", "Disable OCLint") do |_| + options.tools.delete_at(options.tools.index(JSONCompilationDatabase)) + options.tools.delete_at(options.tools.index(OCLint)) + end + + # Optional + opts.on("--disable-slather", "Disable Slather") do |_| + options.tools.delete_at(options.tools.index(Slather)) + end + + # Optional + opts.on("--disable-lizard", "Disable Lizard") do |_| + options.tools.delete_at(options.tools.index(Lizard)) + end + # Optional + opts.on("--disable-fauxpas", "Disable FauxPas") do |_| + options.tools.delete_at(options.tools.index(FauxPas)) + end + + # Optional + opts.on("--disable-upload", "Disable upload to SonarQube server") do |_| + options.upload = false + end + + opts.separator "" + opts.separator "Common options:" + + opts.on("-v", "--verbose", "Run verbosely") do |_| + Logging.logger_level = Logger::DEBUG + end + + # No argument, shows at tail. This will print an options summary. + # Try it and see! + opts.on_tail("-h", "--help", "Show this message") do + puts opts + exit + end end - end \ No newline at end of file + opt_parser.parse!(args) + + end + +end \ No newline at end of file From 02c241ceb56f8a10bc17a43302b6c616c995dad2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gae=CC=88l=20Foppolo?= Date: Sun, 1 Sep 2019 18:41:35 +0200 Subject: [PATCH 20/30] Add ability to skip tool if not installed --- analyzer/helper.rb | 6 ++++-- analyzer/tools/unit_tests.rb | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/analyzer/helper.rb b/analyzer/helper.rb index d12dc5a7..9bc721d5 100644 --- a/analyzer/helper.rb +++ b/analyzer/helper.rb @@ -27,11 +27,13 @@ def available(programs) # Check program is available and return an updated list. private def _available(program) - program.command.values.reduce(true) { |available, tool| + availability = program.command.values.reduce(true) { |available, tool| toolAvailable = system("which #{tool} 2>&1 > /dev/null") - logger.warn("#{tool} is not found in PATH.") if !toolAvailable + logger.warn("#{tool} is not found in PATH") if !toolAvailable available &= toolAvailable } + logger.warn("Skipping #{program}.") if !availability + availability end private diff --git a/analyzer/tools/unit_tests.rb b/analyzer/tools/unit_tests.rb index 2a3e720a..e52ce788 100644 --- a/analyzer/tools/unit_tests.rb +++ b/analyzer/tools/unit_tests.rb @@ -20,7 +20,7 @@ def initialize(options) end def run - logger.info('Running ...') + logger.info('Running...') cmd = "#{self.class.command[:xcodebuild]} clean build-for-testing test" cmd += " -workspace \"#{@workspace}\"" unless @workspace.nil? cmd += " -project \"#{@project}\"" unless !@workspace.nil? From 75cc9a15306f9c040543c755667c8bc218e0649f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gae=CC=88l=20Foppolo?= Date: Sun, 1 Sep 2019 19:08:40 +0200 Subject: [PATCH 21/30] Check number of ObjC files --- analyzer/tools/oclint.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/analyzer/tools/oclint.rb b/analyzer/tools/oclint.rb index 87cfbdca..b54d54c8 100644 --- a/analyzer/tools/oclint.rb +++ b/analyzer/tools/oclint.rb @@ -20,6 +20,9 @@ def initialize(options) def run() logger.info('Running...') @sources.each do |source| + + next unless `find \"#{source}/\" -name '*.m' | wc -l | tr -d ' ' 2>&1` != 0 + report_name = "#{source.tr(' ', '_')}-oclint.xml" cmd = "#{self.class.command[:oclint]}" From f2deed6fe9eeb74e53b629e12cc018a3bf0a81e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gae=CC=88l=20Foppolo?= Date: Tue, 3 Sep 2019 22:33:12 +0200 Subject: [PATCH 22/30] Export some variables to constants --- analyzer/analyzer.rb | 8 +- analyzer/helper.rb | 23 +++-- analyzer/tools/fauxpas.rb | 22 ++-- analyzer/tools/json_compilation_database.rb | 28 +++-- analyzer/tools/lizard.rb | 15 ++- analyzer/tools/oclint.rb | 25 +++-- analyzer/tools/slather.rb | 28 +++-- analyzer/tools/sonar_runner.rb | 4 +- analyzer/tools/sonar_scanner.rb | 4 +- analyzer/tools/swiftlint.rb | 16 ++- analyzer/tools/tool.rb | 2 +- analyzer/tools/unit_tests.rb | 28 +++-- sonar-project.properties | 108 -------------------- 13 files changed, 122 insertions(+), 189 deletions(-) delete mode 100755 sonar-project.properties diff --git a/analyzer/analyzer.rb b/analyzer/analyzer.rb index eb899648..5a52e64a 100644 --- a/analyzer/analyzer.rb +++ b/analyzer/analyzer.rb @@ -31,6 +31,8 @@ def initialize @options.upload = true # upload results to SonarQube by default @options.path = 'sonar-project.properties' + # report folder + @options.report_folder = 'sonar-reports' @helper = Helper.new @@ -42,13 +44,13 @@ def run Options.new.parse(ARGV, @options) # Initiate reports - @helper.bootstrap_reports + @helper.bootstrap_reports(@options.report_folder) # Read Sonar project properties @properties = SonarPropertiesReader.new(@options.path).read tools - reporter if upload + reporter if @options.upload end @@ -59,7 +61,7 @@ def tools # Run tools @options.tools.each do |tool| - tool.new(@properties).run + tool.new(@properties, @options).run end end diff --git a/analyzer/helper.rb b/analyzer/helper.rb index 9bc721d5..f8ae7f93 100644 --- a/analyzer/helper.rb +++ b/analyzer/helper.rb @@ -7,9 +7,9 @@ class Helper # Put default xml files with no tests and no coverage. This is needed to # ensure a file is present, either the Xcode build test step worked or # not. Without this, Sonar Scanner will fail uploading results. - def bootstrap_reports - reports_folder - mandatory_reports + def bootstrap_reports(folder) + reports_folder(folder) + mandatory_reports(folder) end # Check each program is available and return an updated list. @@ -20,7 +20,8 @@ def available(programs) _available(program) end else - _available(programs) + if _available(programs) then programs else nil end + end end @@ -37,20 +38,20 @@ def _available(program) end private - def mandatory_reports + def mandatory_reports(folder) logger.info('Creating default reports') empty_test_report = "" - File.write('sonar-reports/TEST-report.xml', empty_test_report) + File.write("#{folder}/TEST-report.xml", empty_test_report) empty_coverage_report = "" - File.write('sonar-reports/coverage.xml', empty_coverage_report) + File.write("#{folder}/coverage.xml", empty_coverage_report) end private - def reports_folder - logger.info('Deleting and creating directory sonar-reports/') - FileUtils.rm_rf('sonar-reports') - Dir.mkdir('sonar-reports') + def reports_folder(folder) + logger.info("Deleting and creating directory #{folder}") + FileUtils.rm_rf(folder) + Dir.mkdir(folder) end end diff --git a/analyzer/tools/fauxpas.rb b/analyzer/tools/fauxpas.rb index eddb12f7..ae56f8df 100644 --- a/analyzer/tools/fauxpas.rb +++ b/analyzer/tools/fauxpas.rb @@ -1,17 +1,21 @@ require_relative 'tool' class FauxPas < Tool + + @@REPORT_FILE = 'fauxpas.json'.freeze + def self.command { fauxpas: 'fauxpas' } end - def initialize(options) - @workspace = options[:workspace] - @project = options[:project] - @scheme = options[:scheme] - super(options) + def initialize(properties, options) + @workspace = properties[:workspace] + @project = properties[:project] + @scheme = properties[:scheme] + @report_folder = options.report_folder + super(properties, options) end def run() @@ -19,7 +23,9 @@ def run() cmd = "#{self.class.command[:fauxpas]} check -o json #{@project}" cmd += " --workspace #{@workspace}" unless @workspace.nil? cmd += " --scheme #{@scheme}" - cmd += " > sonar-reports/fauxpas.json" + cmd += " -v " + cmd += if logger.level == Logger::DEBUG then "yes" else "no" end + cmd += " > #{@report_folder}/#{@@REPORT_FILE}" logger.debug("Will run `#{cmd}`") system(cmd) end @@ -28,7 +34,7 @@ def run() def validate_settings! # @workspace is optional - fatal_error('A project must be set in order to compute coverage') if @project.nil? - fatal_error('A scheme must be set in order to compute coverage') if @scheme.nil? + fatal_error('A project must be set in order run FauxPas') if @project.nil? + fatal_error('A scheme must be set in order run FauxPas') if @scheme.nil? end end \ No newline at end of file diff --git a/analyzer/tools/json_compilation_database.rb b/analyzer/tools/json_compilation_database.rb index 9fa9bfa2..4780c69b 100644 --- a/analyzer/tools/json_compilation_database.rb +++ b/analyzer/tools/json_compilation_database.rb @@ -1,6 +1,11 @@ require_relative 'tool' class JSONCompilationDatabase < Tool + + @@TIMEOUT = '360'.freeze + @@COMPILE_COMMANDS_FILE = 'compile_commands.json'.freeze + @@XCODEBUILD_FILE = 'xcodebuild.log'.freeze + def self.command { xcodebuild: 'xcodebuild', @@ -8,12 +13,12 @@ def self.command } end - def initialize(options) - @workspace = options[:workspace] - @project = options[:project] - @scheme = options[:scheme] - @simulator = options[:simulator] - super(options) + def initialize(properties, options) + @workspace = properties[:workspace] + @project = properties[:project] + @scheme = properties[:scheme] + @simulator = properties[:simulator] + super(properties, options) end def run @@ -22,9 +27,10 @@ def run cmd += " -workspace \"#{@workspace}\"" unless @workspace.nil? cmd += " -project \"#{@project}\"" unless !@workspace.nil? cmd += " -scheme \"#{@scheme}\"" - cmd += " -destination '#{@simulator}' -destination-timeout 360 COMPILER_INDEX_STORE_ENABLE=NO" unless @simulator.nil? - cmd += " | tee xcodebuild.log" - cmd += " | #{self.class.command[:xcpretty]} -r json-compilation-database -o compile_commands.json" + cmd += " -destination '#{@simulator}' -destination-timeout #{@@TIMEOUT} COMPILER_INDEX_STORE_ENABLE=NO" unless @simulator.nil? + cmd += " -quiet" unless logger.level == Logger::DEBUG + cmd += " | tee #{@@XCODEBUILD_FILE}" + cmd += " | #{self.class.command[:xcpretty]} -r json-compilation-database -o #{@@COMPILE_COMMANDS_FILE}" logger.debug("Will run `#{cmd}`") system(cmd) end @@ -33,8 +39,8 @@ def run def validate_settings! # @workspace is optional - fatal_error('A project must be set in order to compute coverage') if @project.nil? - fatal_error('A scheme must be set in order to build and test the app') if @scheme.nil? + fatal_error('A project must be set in order to compute JSON compilation database') if @project.nil? + fatal_error('A scheme must be set in order to compute JSON compilation database') if @scheme.nil? logger.warn('No simulator specified') if @simulator.nil? end diff --git a/analyzer/tools/lizard.rb b/analyzer/tools/lizard.rb index 938a8067..33dcf528 100644 --- a/analyzer/tools/lizard.rb +++ b/analyzer/tools/lizard.rb @@ -4,15 +4,19 @@ # # @see http://www.lizard.ws class Lizard < Tool + + @@REPORT_FILE = 'lizard-reports.xml'.freeze + def self.command { lizard: 'lizard' } end - def initialize(options) - @sources = options[:sources] - super(options) + def initialize(properties, options) + @sources = properties[:sources] + @report_folder = options.report_folder + super(properties, options) end def run() @@ -21,7 +25,8 @@ def run() @sources.each do |source| cmd += " \"#{source}\"" end - cmd += " > sonar-reports/lizard-reports.xml" + cmd += " --verbose" + cmd += " > #{report_folder}/#{@@REPORT_FILE}" logger.debug("Will run `#{cmd}`") system(cmd) end @@ -29,6 +34,6 @@ def run() private def validate_settings! - fatal_error('Sources must be set in order to compute complexity') if @sources.nil? + fatal_error('Sources must be set in order to compute Lizard complexity') if @sources.nil? end end \ No newline at end of file diff --git a/analyzer/tools/oclint.rb b/analyzer/tools/oclint.rb index b54d54c8..204cb588 100644 --- a/analyzer/tools/oclint.rb +++ b/analyzer/tools/oclint.rb @@ -3,8 +3,9 @@ class OCLint < Tool - MAX_PRIORITY = 10000 - LONG_LINE_THRESHOLD = 250 + @@MAX_PRIORITY = 10000 + @@LONG_LINE_THRESHOLD = 250 + @@REPORT_FILE = '-oclint.xml'.freeze def self.command { @@ -12,9 +13,10 @@ def self.command } end - def initialize(options) - @sources = options[:sources] - super(options) + def initialize(properties, options) + @sources = properties[:sources] + @report_folder = options.report_folder + super(properties, options) end def run() @@ -23,14 +25,15 @@ def run() next unless `find \"#{source}/\" -name '*.m' | wc -l | tr -d ' ' 2>&1` != 0 - report_name = "#{source.tr(' ', '_')}-oclint.xml" + report_name = "#{source.tr(' ', '_')}#{@@REPORT_FILE}" cmd = "#{self.class.command[:oclint]}" - cmd += " --include \"#{source}\"" - cmd += " -- -rc LONG_LINE=#{LONG_LINE_THRESHOLD}" - cmd += " -max-priority-1 #{MAX_PRIORITY} -max-priority-2 #{MAX_PRIORITY} -max-priority-3 #{MAX_PRIORITY}" + cmd += " -v" if logger.level == Logger::DEBUG + cmd += " --include #{source}" + cmd += " -- -rc LONG_LINE=#{@@LONG_LINE_THRESHOLD}" + cmd += " -max-priority-1 #{@@MAX_PRIORITY} -max-priority-2 #{@@MAX_PRIORITY} -max-priority-3 #{@@MAX_PRIORITY}" cmd += " -report-type pmd" - cmd += " -o sonar-reports/#{report_name}" + cmd += " -o #{report_folder}/#{report_name}" logger.debug("Will run `#{cmd}`") system(cmd) @@ -41,7 +44,7 @@ def run() private def validate_settings! - fatal_error('Sources must be set in order to lint') if @sources.nil? + fatal_error('Sources must be set in order to run OCLint') if @sources.nil? fatal_error("compile_commands.json not found") unless File.exist?("compile_commands.json") end end \ No newline at end of file diff --git a/analyzer/tools/slather.rb b/analyzer/tools/slather.rb index c1b514d4..3f4f5f2f 100644 --- a/analyzer/tools/slather.rb +++ b/analyzer/tools/slather.rb @@ -2,25 +2,31 @@ require_relative 'tool' class Slather < Tool + + @@REPORT_FILE_DEFAULT = 'cobertura.xml'.freeze + @@REPORT_FILE = 'coverage-swift.xml'.freeze + def self.command { slather: 'slather' } end - def initialize(options) - @workspace = options[:workspace] - @project = options[:project] - @scheme = options[:scheme] - @exclude_from_coverage = options[:exclude_from_coverage] - @binary_names = options[:binary_names] - super(options) + def initialize(properties, options) + @workspace = properties[:workspace] + @project = properties[:project] + @scheme = properties[:scheme] + @exclude_from_coverage = properties[:exclude_from_coverage] + @binary_names = properties[:binary_names] + @report_folder = options.report_folder + super(properties, options) end def run() logger.info('Running...') cmd = "#{self.class.command[:slather]} coverage" + cmd += " --verbose" if logger.level == Logger::DEBUG unless @binary_names.nil? @binary_names.each do |binary| cmd += " --binary-basename \"#{binary}\"" @@ -31,13 +37,13 @@ def run() cmd += " -i \"#{exclusion}\"" end end - cmd += " --input-format profdata --cobertura-xml --output-directory sonar-reports" + cmd += " --input-format profdata --cobertura-xml --output-directory #{report_folder}" cmd += " --workspace #{@workspace}" unless @workspace.nil? cmd += " --scheme #{@scheme} #{@project}" logger.debug("Will run `#{cmd}`") system(cmd) - FileUtils.mv('sonar-reports/cobertura.xml', 'sonar-reports/coverage-swift.xml') + FileUtils.mv("#{report_folder}/#{@@REPORT_FILE_DEFAULT}", "#{report_folder}/#{@@REPORT_FILE}") end @@ -45,8 +51,8 @@ def run() def validate_settings! # @workspace is optional - fatal_error('A project must be set in order to compute coverage') if @project.nil? - fatal_error('A scheme must be set in order to compute coverage') if @scheme.nil? + fatal_error('A project must be set in order to run Slather') if @project.nil? + fatal_error('A scheme must be set in order to run Slather') if @scheme.nil? # @exclude_from_coverage is optional # @binary_names is optional end diff --git a/analyzer/tools/sonar_runner.rb b/analyzer/tools/sonar_runner.rb index c5f8f987..10ad1794 100644 --- a/analyzer/tools/sonar_runner.rb +++ b/analyzer/tools/sonar_runner.rb @@ -7,8 +7,8 @@ def self.command } end - def initialize(options) - super(options) + def initialize(properties, options) + super(properties, options) end def run() diff --git a/analyzer/tools/sonar_scanner.rb b/analyzer/tools/sonar_scanner.rb index e52dd228..62053ffc 100644 --- a/analyzer/tools/sonar_scanner.rb +++ b/analyzer/tools/sonar_scanner.rb @@ -7,8 +7,8 @@ def self.command } end - def initialize(options) - super(options) + def initialize(properties, options) + super(properties, options) end def run() diff --git a/analyzer/tools/swiftlint.rb b/analyzer/tools/swiftlint.rb index 66c8a7ad..7e0cf6b5 100644 --- a/analyzer/tools/swiftlint.rb +++ b/analyzer/tools/swiftlint.rb @@ -8,22 +8,28 @@ # # https://github.com/realm/SwiftLint class SwiftLint < Tool + + @@REPORT_FILE = '-swiftlint.txt'.freeze + def self.command { swiftlint: 'swiftlint' } end - def initialize(options) - @sources = options[:sources] - super(options) + def initialize(properties, options) + @sources = properties[:sources] + @report_folder = options.report_folder + super(properties, options) end def run() logger.info('Running...') @sources.each do |source| - report_name = "#{source.tr(' ', '_')}-swiftlint.txt" - cmd = "#{self.class.command[:swiftlint]} lint --path \"#{source}\" > sonar-reports/#{report_name}" + report_name = "#{source.tr(' ', '_')}#{@@REPORT_FILE}" + cmd = "#{self.class.command[:swiftlint]} lint --path \"#{source}\"" + cmd += " --quiet" unless logger.level == Logger::DEBUG + cmd += " > #{report_folder}/#{report_name}" logger.debug("Will run `#{cmd}`") system(cmd) end diff --git a/analyzer/tools/tool.rb b/analyzer/tools/tool.rb index 60c56797..06901d3b 100644 --- a/analyzer/tools/tool.rb +++ b/analyzer/tools/tool.rb @@ -11,7 +11,7 @@ class Tool def self.command end - def initialize(_options) + def initialize(properties, options) validate_settings! end diff --git a/analyzer/tools/unit_tests.rb b/analyzer/tools/unit_tests.rb index e52ce788..7195be99 100644 --- a/analyzer/tools/unit_tests.rb +++ b/analyzer/tools/unit_tests.rb @@ -2,6 +2,10 @@ # Runs unit tests using Xcode with `xcodebuild` class UnitTests < Tool + + @@TIMEOUT = '60'.freeze + @@REPORT_FILE = 'TEST-report.xml' + def self.command { xcodebuild: 'xcodebuild', @@ -9,14 +13,15 @@ def self.command } end - def initialize(options) - @workspace = options[:workspace] - @project = options[:project] - @scheme = options[:scheme] - @configuration = options[:configuration] - @simulator = options[:simulator] - @exclude_from_coverage = options[:exclude_from_coverage] - super(options) + def initialize(properties, options) + @workspace = properties[:workspace] + @project = properties[:project] + @scheme = properties[:scheme] + @configuration = properties[:configuration] + @simulator = properties[:simulator] + @exclude_from_coverage = properties[:exclude_from_coverage] + @report_folder = options.report_folder + super(properties, options) end def run @@ -27,9 +32,10 @@ def run cmd += " -scheme \"#{@scheme}\"" cmd += " -configuration \"#{@configuration}\"" cmd += " -enableCodeCoverage YES" - cmd += " -destination '#{@simulator}' -destination-timeout 60" unless @simulator.nil? + cmd += " -destination '#{@simulator}' -destination-timeout #{@@TIMEOUT}" unless @simulator.nil? + cmd += " -quiet" unless logger.level == Logger::DEBUG cmd += " | tee xcodebuild.log" - cmd += " | #{self.class.command[:xcpretty]} -t --report junit -o sonar-reports/TEST-report.xml" + cmd += " | #{self.class.command[:xcpretty]} -t --report junit -o #{report_folder}/#{@@REPORT_FILE}" logger.debug("Will run `#{cmd}`") system(cmd) end @@ -38,7 +44,7 @@ def run def validate_settings! # @workspace is optional - fatal_error('A project must be set in order to compute coverage') if @project.nil? + fatal_error('A project must be set in order to run test') if @project.nil? fatal_error('A scheme must be set in order to build and test the app') if @scheme.nil? fatal_error('A configuration must be set in order to build and test the app') if @configuration.nil? logger.warn('No simulator specified') if @simulator.nil? diff --git a/sonar-project.properties b/sonar-project.properties deleted file mode 100755 index b793770f..00000000 --- a/sonar-project.properties +++ /dev/null @@ -1,108 +0,0 @@ -# -# Swift SonarQube Plugin - Enables analysis of Swift and Objective-C projects into SonarQube. -# Copyright © 2015 Backelite (${email}) -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with this program. If not, see . -# - -sonar.projectKey=prjKey -sonar.projectName=prjName -# Number version (can be found automatically in plist, just comment this line) -sonar.projectVersion=1.0 - -# Comment if you have a project with mixed ObjC / Swift -sonar.language=swift - -# Project description -sonar.projectDescription=prjDescription - -# Path to source directories -sonar.sources=SourceDir -# Path to test directories (comment if no test) -sonar.tests=TestDir - -# Destination Simulator to run surefire -# As string expected in destination argument of xcodebuild command -# Example = sonar.swift.simulator=platform=iOS Simulator,name=iPhone 6,OS=9.2 -sonar.swift.simulator=platform=iOS Simulator,name=iPhone X,OS=latest - -# Xcode project configuration (.xcodeproj) -# and use the later to specify which project(s) to include in the analysis (comma separated list) -# Specify either xcodeproj or xcodeproj + xcworkspace -#sonar.swift.project=MyPrj.xcodeproj -#sonar.swift.workspace=MyWrkSpc.xcworkspace - -# Scheme to build your application -sonar.swift.appScheme=MyScheme - -# Specify your appname when different from targeted scheme. -# Or when slather fails with 'No product binary found' -# You can also provide a list of framework names to analyse for coverage. -# This will be something like "myApp" or "myApp,myFramework" -# sonar.coverage.binaryNames=myApp,myFramework - -# Configuration to use for your scheme. if you do not specify that the default will be Debug -sonar.swift.appConfiguration=MyConfiguration - -########################## -# Optional configuration # -########################## -# Encoding of the source code -sonar.sourceEncoding=UTF-8 -# SCM -# sonar.scm.enabled=true -# sonar.scm.url=scm:git:http://xxx - -# JUnit report generated by run-sonar.sh is stored in sonar-reports/TEST-report.xml -# Change it only if you generate the file on your own -# The XML files have to be prefixed by TEST- otherwise they are not processed -# sonar.junit.reportsPath=sonar-reports/ - -# Lizard report generated by run-sonar.sh is stored in sonar-reports/lizard-report.xml -# Change it only if you generate the file on your own -# sonar.swift.lizard.report=sonar-reports/lizard-report.xml - -# Cobertura report generated by run-sonar.sh is stored in sonar-reports/coverage-swift.xml -# Change it only if you generate the file on your own -# sonar.swift.coverage.reportPattern=sonar-reports/coverage-swift*.xml - -# OCLint report generated by run-sonar.sh is stored in sonar-reports/oclint.xml -# Change it only if you generate the file on your own -# sonar.swift.swiftlint.report=sonar-reports/*swiftlint.txt - -# Change it only if you generate the file on your own -# sonar.swift.tailor.report=sonar-reports/*tailor.txt - -# Paths to exclude from coverage report (surefire, 3rd party libraries etc.) -# sonar.swift.excludedPathsFromCoverage=pattern1,pattern2 -sonar.swift.excludedPathsFromCoverage=.*Tests.* - -# Ability to skip tests (such as UI Tests running long time) -# Example = sonar.swift.skipTests=UITests - -########################## -# Tailor configuration # -########################## -# Tailor configuration -# -l,--max-line-length=<0-999> maximum Line length (in characters) -# --list-files display Swift source files to be analyzed -# --max-class-length=<0-999> maximum Class length (in lines) -# --max-closure-length=<0-999> maximum Closure length (in lines) -# --max-file-length=<0-999> maximum File length (in lines) -# --max-function-length=<0-999> maximum Function length (in lines) -# --max-name-length=<0-999> maximum Identifier name length (in characters) -# --max-severity= maximum severity -# --max-struct-length=<0-999> maximum Struct length (in lines) -# --min-name-length=<1-999> minimum Identifier name length (in characters) -sonar.swift.tailor.config=--no-color --max-line-length=100 --max-file-length=500 --max-name-length=40 --max-name-length=40 --min-name-length=4 From 0fe10e11b2931cfebc5f4d5758cec25c64ee4c45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gae=CC=88l=20Foppolo?= Date: Tue, 3 Sep 2019 22:33:31 +0200 Subject: [PATCH 23/30] Fix variable --- analyzer/properties_reader.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/analyzer/properties_reader.rb b/analyzer/properties_reader.rb index 983aaf58..ce5de611 100644 --- a/analyzer/properties_reader.rb +++ b/analyzer/properties_reader.rb @@ -59,7 +59,7 @@ def validate_settings!(options) def check_file(file) unless file.nil? - fatal_error("#{file} not found") unless File.exist?("file") + fatal_error("#{file} not found") unless File.exist?(file) end end From 3989160289693068e49c0b194812f18907e6f6eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gae=CC=88l=20Foppolo?= Date: Sun, 8 Sep 2019 11:24:43 +0200 Subject: [PATCH 24/30] Fix naming and remove some verbose parameters --- analyzer/analyzer.rb | 2 +- analyzer/tools/json_compilation_database.rb | 1 - analyzer/tools/lizard.rb | 5 ++--- analyzer/tools/oclint.rb | 2 +- analyzer/tools/slather.rb | 4 ++-- analyzer/tools/swiftlint.rb | 2 +- analyzer/tools/unit_tests.rb | 2 +- 7 files changed, 8 insertions(+), 10 deletions(-) diff --git a/analyzer/analyzer.rb b/analyzer/analyzer.rb index 5a52e64a..5e38dc57 100644 --- a/analyzer/analyzer.rb +++ b/analyzer/analyzer.rb @@ -71,7 +71,7 @@ def reporter @options.reporter = @helper.available(@options.reporter) # Send reports - @options.reporter.new([]).run unless @options.reporter.nil? + @options.reporter.new(@properties, @options).run unless @options.reporter.nil? end diff --git a/analyzer/tools/json_compilation_database.rb b/analyzer/tools/json_compilation_database.rb index 4780c69b..0c4d0a64 100644 --- a/analyzer/tools/json_compilation_database.rb +++ b/analyzer/tools/json_compilation_database.rb @@ -28,7 +28,6 @@ def run cmd += " -project \"#{@project}\"" unless !@workspace.nil? cmd += " -scheme \"#{@scheme}\"" cmd += " -destination '#{@simulator}' -destination-timeout #{@@TIMEOUT} COMPILER_INDEX_STORE_ENABLE=NO" unless @simulator.nil? - cmd += " -quiet" unless logger.level == Logger::DEBUG cmd += " | tee #{@@XCODEBUILD_FILE}" cmd += " | #{self.class.command[:xcpretty]} -r json-compilation-database -o #{@@COMPILE_COMMANDS_FILE}" logger.debug("Will run `#{cmd}`") diff --git a/analyzer/tools/lizard.rb b/analyzer/tools/lizard.rb index 33dcf528..65409efd 100644 --- a/analyzer/tools/lizard.rb +++ b/analyzer/tools/lizard.rb @@ -5,7 +5,7 @@ # @see http://www.lizard.ws class Lizard < Tool - @@REPORT_FILE = 'lizard-reports.xml'.freeze + @@REPORT_FILE = 'lizard-report.xml'.freeze def self.command { @@ -25,8 +25,7 @@ def run() @sources.each do |source| cmd += " \"#{source}\"" end - cmd += " --verbose" - cmd += " > #{report_folder}/#{@@REPORT_FILE}" + cmd += " > #{@report_folder}/#{@@REPORT_FILE}" logger.debug("Will run `#{cmd}`") system(cmd) end diff --git a/analyzer/tools/oclint.rb b/analyzer/tools/oclint.rb index 204cb588..b7dc9cf7 100644 --- a/analyzer/tools/oclint.rb +++ b/analyzer/tools/oclint.rb @@ -33,7 +33,7 @@ def run() cmd += " -- -rc LONG_LINE=#{@@LONG_LINE_THRESHOLD}" cmd += " -max-priority-1 #{@@MAX_PRIORITY} -max-priority-2 #{@@MAX_PRIORITY} -max-priority-3 #{@@MAX_PRIORITY}" cmd += " -report-type pmd" - cmd += " -o #{report_folder}/#{report_name}" + cmd += " -o #{@report_folder}/#{report_name}" logger.debug("Will run `#{cmd}`") system(cmd) diff --git a/analyzer/tools/slather.rb b/analyzer/tools/slather.rb index 3f4f5f2f..36eed459 100644 --- a/analyzer/tools/slather.rb +++ b/analyzer/tools/slather.rb @@ -37,13 +37,13 @@ def run() cmd += " -i \"#{exclusion}\"" end end - cmd += " --input-format profdata --cobertura-xml --output-directory #{report_folder}" + cmd += " --input-format profdata --cobertura-xml --output-directory #{@report_folder}" cmd += " --workspace #{@workspace}" unless @workspace.nil? cmd += " --scheme #{@scheme} #{@project}" logger.debug("Will run `#{cmd}`") system(cmd) - FileUtils.mv("#{report_folder}/#{@@REPORT_FILE_DEFAULT}", "#{report_folder}/#{@@REPORT_FILE}") + FileUtils.mv("#{@report_folder}/#{@@REPORT_FILE_DEFAULT}", "#{@report_folder}/#{@@REPORT_FILE}") end diff --git a/analyzer/tools/swiftlint.rb b/analyzer/tools/swiftlint.rb index 7e0cf6b5..15761d8a 100644 --- a/analyzer/tools/swiftlint.rb +++ b/analyzer/tools/swiftlint.rb @@ -29,7 +29,7 @@ def run() report_name = "#{source.tr(' ', '_')}#{@@REPORT_FILE}" cmd = "#{self.class.command[:swiftlint]} lint --path \"#{source}\"" cmd += " --quiet" unless logger.level == Logger::DEBUG - cmd += " > #{report_folder}/#{report_name}" + cmd += " > #{@report_folder}/#{report_name}" logger.debug("Will run `#{cmd}`") system(cmd) end diff --git a/analyzer/tools/unit_tests.rb b/analyzer/tools/unit_tests.rb index 7195be99..264ff7e0 100644 --- a/analyzer/tools/unit_tests.rb +++ b/analyzer/tools/unit_tests.rb @@ -35,7 +35,7 @@ def run cmd += " -destination '#{@simulator}' -destination-timeout #{@@TIMEOUT}" unless @simulator.nil? cmd += " -quiet" unless logger.level == Logger::DEBUG cmd += " | tee xcodebuild.log" - cmd += " | #{self.class.command[:xcpretty]} -t --report junit -o #{report_folder}/#{@@REPORT_FILE}" + cmd += " | #{self.class.command[:xcpretty]} -t --report junit -o #{@report_folder}/#{@@REPORT_FILE}" logger.debug("Will run `#{cmd}`") system(cmd) end From 4fe89da524b510bbba093b4586729f7a917b1d1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gae=CC=88l=20Foppolo?= Date: Sun, 8 Sep 2019 18:48:52 +0200 Subject: [PATCH 25/30] Begin to create gem --- analyzer/Gemfile.lock | 56 ------------------- analyzer/analyzer.gemspec | 19 +++++++ analyzer/{ => lib}/analyzer.rb | 26 ++++----- analyzer/{ => lib}/canfail.rb | 0 analyzer/{ => lib}/helper.rb | 2 +- analyzer/{ => lib}/logging.rb | 0 analyzer/{ => lib}/options.rb | 0 analyzer/{ => lib}/properties_reader.rb | 6 +- analyzer/{ => lib}/tools/fauxpas.rb | 2 +- .../tools/json_compilation_database.rb | 2 +- analyzer/{ => lib}/tools/lizard.rb | 2 +- analyzer/{ => lib}/tools/oclint.rb | 2 +- analyzer/{ => lib}/tools/slather.rb | 2 +- analyzer/{ => lib}/tools/sonar_runner.rb | 2 +- analyzer/{ => lib}/tools/sonar_scanner.rb | 2 +- analyzer/{ => lib}/tools/swiftlint.rb | 2 +- analyzer/{ => lib}/tools/tool.rb | 4 +- analyzer/{ => lib}/tools/unit_tests.rb | 9 ++- 18 files changed, 55 insertions(+), 83 deletions(-) delete mode 100644 analyzer/Gemfile.lock create mode 100644 analyzer/analyzer.gemspec rename analyzer/{ => lib}/analyzer.rb (75%) rename analyzer/{ => lib}/canfail.rb (100%) rename analyzer/{ => lib}/helper.rb (98%) rename analyzer/{ => lib}/logging.rb (100%) rename analyzer/{ => lib}/options.rb (100%) rename analyzer/{ => lib}/properties_reader.rb (92%) rename analyzer/{ => lib}/tools/fauxpas.rb (97%) rename analyzer/{ => lib}/tools/json_compilation_database.rb (98%) rename analyzer/{ => lib}/tools/lizard.rb (96%) rename analyzer/{ => lib}/tools/oclint.rb (97%) rename analyzer/{ => lib}/tools/slather.rb (98%) rename analyzer/{ => lib}/tools/sonar_runner.rb (91%) rename analyzer/{ => lib}/tools/sonar_scanner.rb (91%) rename analyzer/{ => lib}/tools/swiftlint.rb (97%) rename analyzer/{ => lib}/tools/tool.rb (82%) rename analyzer/{ => lib}/tools/unit_tests.rb (90%) diff --git a/analyzer/Gemfile.lock b/analyzer/Gemfile.lock deleted file mode 100644 index 366e94ab..00000000 --- a/analyzer/Gemfile.lock +++ /dev/null @@ -1,56 +0,0 @@ -GIT - remote: https://github.com/Backelite/xcpretty - revision: 70668d61562744b3d22a309b1c49a15805f7fa75 - specs: - xcpretty (0.2.2) - rouge (~> 1.8) - -GEM - remote: https://rubygems.org/ - specs: - CFPropertyList (3.0.1) - activesupport (4.2.11.1) - i18n (~> 0.7) - minitest (~> 5.1) - thread_safe (~> 0.3, >= 0.3.4) - tzinfo (~> 1.1) - atomos (0.1.3) - claide (1.0.3) - clamp (1.3.1) - colored2 (3.1.2) - concurrent-ruby (1.1.5) - i18n (0.9.5) - concurrent-ruby (~> 1.0) - java-properties (0.2.0) - mini_portile2 (2.4.0) - minitest (5.11.3) - nanaimo (0.2.6) - nokogiri (1.10.4) - mini_portile2 (~> 2.4.0) - rouge (1.11.1) - slather (2.4.7) - CFPropertyList (>= 2.2, < 4) - activesupport (>= 4.0.2, < 5) - clamp (~> 1.3) - nokogiri (~> 1.8) - xcodeproj (~> 1.7) - thread_safe (0.3.6) - tzinfo (1.2.5) - thread_safe (~> 0.1) - xcodeproj (1.12.0) - CFPropertyList (>= 2.3.3, < 4.0) - atomos (~> 0.1.3) - claide (>= 1.0.2, < 2.0) - colored2 (~> 3.1) - nanaimo (~> 0.2.6) - -PLATFORMS - ruby - -DEPENDENCIES - java-properties (= 0.2.0) - slather (= 2.4.7) - xcpretty (= 0.2.2)! - -BUNDLED WITH - 2.0.2 diff --git a/analyzer/analyzer.gemspec b/analyzer/analyzer.gemspec new file mode 100644 index 00000000..bd75a83c --- /dev/null +++ b/analyzer/analyzer.gemspec @@ -0,0 +1,19 @@ +Gem::Specification.new do |s| + s.name = "analyzer" + s.version = "0.0.1" + s.summary = "SonarSwift plugin analyzer" + s.authors = ["Gaël FOppolo"] + s.description = "SonarSwift plugin analyzer" + + s.license = 'MIT' + s.required_ruby_version = '>= 2.0.0' + + s.files = `git ls-files`.split($/) + #s.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } + s.require_paths = ["lib"] + + #s.add_runtime_dependency 'java-properties', "= 0.2.0" + #s.add_runtime_dependency 'xcpretty', "= 0.2.2", git: "https://github.com/Backelite/xcpretty" + #s.add_runtime_dependency 'slather', "= 2.4.7" + +end \ No newline at end of file diff --git a/analyzer/analyzer.rb b/analyzer/lib/analyzer.rb similarity index 75% rename from analyzer/analyzer.rb rename to analyzer/lib/analyzer.rb index 5e38dc57..9d2033e7 100644 --- a/analyzer/analyzer.rb +++ b/analyzer/lib/analyzer.rb @@ -1,18 +1,18 @@ #!/usr/bin/env ruby require 'ostruct' -require_relative 'logging' -require_relative 'tools/swiftlint' -require_relative 'tools/lizard' -require_relative 'tools/sonar_scanner' -require_relative 'tools/sonar_runner' -require_relative 'tools/unit_tests' -require_relative 'tools/slather' -require_relative 'tools/oclint' -require_relative 'tools/fauxpas' -require_relative 'tools/json_compilation_database' -require_relative 'options' -require_relative 'properties_reader' -require_relative 'helper' +require 'logging' +require 'tools/swiftlint' +require 'tools/lizard' +require 'tools/sonar_scanner' +require 'tools/sonar_runner' +require 'tools/unit_tests' +require 'tools/slather' +require 'tools/oclint' +require 'tools/fauxpas' +require 'tools/json_compilation_database' +require 'options' +require 'properties_reader' +require 'helper' # Entry point of the script. # diff --git a/analyzer/canfail.rb b/analyzer/lib/canfail.rb similarity index 100% rename from analyzer/canfail.rb rename to analyzer/lib/canfail.rb diff --git a/analyzer/helper.rb b/analyzer/lib/helper.rb similarity index 98% rename from analyzer/helper.rb rename to analyzer/lib/helper.rb index f8ae7f93..ba29f790 100644 --- a/analyzer/helper.rb +++ b/analyzer/lib/helper.rb @@ -1,5 +1,5 @@ require 'fileutils' -require_relative 'logging' +require 'logging' class Helper include Logging diff --git a/analyzer/logging.rb b/analyzer/lib/logging.rb similarity index 100% rename from analyzer/logging.rb rename to analyzer/lib/logging.rb diff --git a/analyzer/options.rb b/analyzer/lib/options.rb similarity index 100% rename from analyzer/options.rb rename to analyzer/lib/options.rb diff --git a/analyzer/properties_reader.rb b/analyzer/lib/properties_reader.rb similarity index 92% rename from analyzer/properties_reader.rb rename to analyzer/lib/properties_reader.rb index ce5de611..570e9d22 100644 --- a/analyzer/properties_reader.rb +++ b/analyzer/lib/properties_reader.rb @@ -1,5 +1,5 @@ -require_relative 'logging' -require_relative 'canfail' +require 'logging' +require 'canfail' require 'fileutils' require 'java-properties' @@ -38,6 +38,8 @@ def read_properties(properties) options[:exclude_from_coverage] = options[:exclude_from_coverage].split(',') unless options[:exclude_from_coverage].nil? options[:binary_names] = properties[:'sonar.coverage.binaryNames'] options[:binary_names] = options[:binary_names].split(',') unless options[:binary_names].nil? + options[:skip_tests] = properties[:'sonar.swift.skipTests'] + options[:skip_tests] = options[:skip_tests].split(',') unless options[:skip_tests].nil? options end diff --git a/analyzer/tools/fauxpas.rb b/analyzer/lib/tools/fauxpas.rb similarity index 97% rename from analyzer/tools/fauxpas.rb rename to analyzer/lib/tools/fauxpas.rb index ae56f8df..64e61da8 100644 --- a/analyzer/tools/fauxpas.rb +++ b/analyzer/lib/tools/fauxpas.rb @@ -1,4 +1,4 @@ -require_relative 'tool' +require 'tool' class FauxPas < Tool diff --git a/analyzer/tools/json_compilation_database.rb b/analyzer/lib/tools/json_compilation_database.rb similarity index 98% rename from analyzer/tools/json_compilation_database.rb rename to analyzer/lib/tools/json_compilation_database.rb index 0c4d0a64..75032243 100644 --- a/analyzer/tools/json_compilation_database.rb +++ b/analyzer/lib/tools/json_compilation_database.rb @@ -1,4 +1,4 @@ -require_relative 'tool' +require 'tool' class JSONCompilationDatabase < Tool diff --git a/analyzer/tools/lizard.rb b/analyzer/lib/tools/lizard.rb similarity index 96% rename from analyzer/tools/lizard.rb rename to analyzer/lib/tools/lizard.rb index 65409efd..e119abad 100644 --- a/analyzer/tools/lizard.rb +++ b/analyzer/lib/tools/lizard.rb @@ -1,4 +1,4 @@ -require_relative 'tool' +require 'tool' # Lizard computes the code complexity. # diff --git a/analyzer/tools/oclint.rb b/analyzer/lib/tools/oclint.rb similarity index 97% rename from analyzer/tools/oclint.rb rename to analyzer/lib/tools/oclint.rb index b7dc9cf7..d9c5e79d 100644 --- a/analyzer/tools/oclint.rb +++ b/analyzer/lib/tools/oclint.rb @@ -1,4 +1,4 @@ -require_relative 'tool' +require 'tool' require 'fileutils' class OCLint < Tool diff --git a/analyzer/tools/slather.rb b/analyzer/lib/tools/slather.rb similarity index 98% rename from analyzer/tools/slather.rb rename to analyzer/lib/tools/slather.rb index 36eed459..97cd1775 100644 --- a/analyzer/tools/slather.rb +++ b/analyzer/lib/tools/slather.rb @@ -1,5 +1,5 @@ require 'fileutils' -require_relative 'tool' +require 'tool' class Slather < Tool diff --git a/analyzer/tools/sonar_runner.rb b/analyzer/lib/tools/sonar_runner.rb similarity index 91% rename from analyzer/tools/sonar_runner.rb rename to analyzer/lib/tools/sonar_runner.rb index 10ad1794..3412ccb2 100644 --- a/analyzer/tools/sonar_runner.rb +++ b/analyzer/lib/tools/sonar_runner.rb @@ -1,4 +1,4 @@ -require_relative 'tool' +require 'tool' class SonarRunner < Tool def self.command diff --git a/analyzer/tools/sonar_scanner.rb b/analyzer/lib/tools/sonar_scanner.rb similarity index 91% rename from analyzer/tools/sonar_scanner.rb rename to analyzer/lib/tools/sonar_scanner.rb index 62053ffc..b39c19bd 100644 --- a/analyzer/tools/sonar_scanner.rb +++ b/analyzer/lib/tools/sonar_scanner.rb @@ -1,4 +1,4 @@ -require_relative 'tool' +require 'tool' class SonarScanner < Tool def self.command diff --git a/analyzer/tools/swiftlint.rb b/analyzer/lib/tools/swiftlint.rb similarity index 97% rename from analyzer/tools/swiftlint.rb rename to analyzer/lib/tools/swiftlint.rb index 15761d8a..50a39a04 100644 --- a/analyzer/tools/swiftlint.rb +++ b/analyzer/lib/tools/swiftlint.rb @@ -1,4 +1,4 @@ -require_relative 'tool' +require 'tool' # SwiftLint checks code style and conventions. # diff --git a/analyzer/tools/tool.rb b/analyzer/lib/tools/tool.rb similarity index 82% rename from analyzer/tools/tool.rb rename to analyzer/lib/tools/tool.rb index 06901d3b..21d970e9 100644 --- a/analyzer/tools/tool.rb +++ b/analyzer/lib/tools/tool.rb @@ -1,5 +1,5 @@ -require_relative '../logging' -require_relative '../canfail' +require '../logging' +require '../canfail' # A base class for tool wrappers. # diff --git a/analyzer/tools/unit_tests.rb b/analyzer/lib/tools/unit_tests.rb similarity index 90% rename from analyzer/tools/unit_tests.rb rename to analyzer/lib/tools/unit_tests.rb index 264ff7e0..26c3d03f 100644 --- a/analyzer/tools/unit_tests.rb +++ b/analyzer/lib/tools/unit_tests.rb @@ -1,4 +1,4 @@ -require_relative 'tool' +require 'tool' # Runs unit tests using Xcode with `xcodebuild` class UnitTests < Tool @@ -20,6 +20,7 @@ def initialize(properties, options) @configuration = properties[:configuration] @simulator = properties[:simulator] @exclude_from_coverage = properties[:exclude_from_coverage] + @skip_tests = properties[:skip_tests] @report_folder = options.report_folder super(properties, options) end @@ -33,6 +34,11 @@ def run cmd += " -configuration \"#{@configuration}\"" cmd += " -enableCodeCoverage YES" cmd += " -destination '#{@simulator}' -destination-timeout #{@@TIMEOUT}" unless @simulator.nil? + unless @skip_tests.nil? + @skip_tests.each do |test| + cmd += " -skip-testing:#{test}" + end + end cmd += " -quiet" unless logger.level == Logger::DEBUG cmd += " | tee xcodebuild.log" cmd += " | #{self.class.command[:xcpretty]} -t --report junit -o #{@report_folder}/#{@@REPORT_FILE}" @@ -49,6 +55,7 @@ def validate_settings! fatal_error('A configuration must be set in order to build and test the app') if @configuration.nil? logger.warn('No simulator specified') if @simulator.nil? # @exclude_from_coverage is optional + # @skip_tests is optional end end \ No newline at end of file From 7a2fa535820affb619804db4a1ddd481fb1add12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gae=CC=88l=20Foppolo?= Date: Sun, 8 Sep 2019 18:56:00 +0200 Subject: [PATCH 26/30] Fix paths --- analyzer/lib/tools/fauxpas.rb | 2 +- analyzer/lib/tools/json_compilation_database.rb | 2 +- analyzer/lib/tools/lizard.rb | 2 +- analyzer/lib/tools/oclint.rb | 2 +- analyzer/lib/tools/slather.rb | 2 +- analyzer/lib/tools/sonar_runner.rb | 2 +- analyzer/lib/tools/sonar_scanner.rb | 2 +- analyzer/lib/tools/swiftlint.rb | 2 +- analyzer/lib/tools/tool.rb | 4 ++-- analyzer/lib/tools/unit_tests.rb | 2 +- 10 files changed, 11 insertions(+), 11 deletions(-) diff --git a/analyzer/lib/tools/fauxpas.rb b/analyzer/lib/tools/fauxpas.rb index 64e61da8..4df0f2f9 100644 --- a/analyzer/lib/tools/fauxpas.rb +++ b/analyzer/lib/tools/fauxpas.rb @@ -1,4 +1,4 @@ -require 'tool' +require 'tools/tool' class FauxPas < Tool diff --git a/analyzer/lib/tools/json_compilation_database.rb b/analyzer/lib/tools/json_compilation_database.rb index 75032243..e1b20987 100644 --- a/analyzer/lib/tools/json_compilation_database.rb +++ b/analyzer/lib/tools/json_compilation_database.rb @@ -1,4 +1,4 @@ -require 'tool' +require 'tools/tool' class JSONCompilationDatabase < Tool diff --git a/analyzer/lib/tools/lizard.rb b/analyzer/lib/tools/lizard.rb index e119abad..a27bff96 100644 --- a/analyzer/lib/tools/lizard.rb +++ b/analyzer/lib/tools/lizard.rb @@ -1,4 +1,4 @@ -require 'tool' +require 'tools/tool' # Lizard computes the code complexity. # diff --git a/analyzer/lib/tools/oclint.rb b/analyzer/lib/tools/oclint.rb index d9c5e79d..b25a0414 100644 --- a/analyzer/lib/tools/oclint.rb +++ b/analyzer/lib/tools/oclint.rb @@ -1,4 +1,4 @@ -require 'tool' +require 'tools/tool' require 'fileutils' class OCLint < Tool diff --git a/analyzer/lib/tools/slather.rb b/analyzer/lib/tools/slather.rb index 97cd1775..da7d76d8 100644 --- a/analyzer/lib/tools/slather.rb +++ b/analyzer/lib/tools/slather.rb @@ -1,5 +1,5 @@ require 'fileutils' -require 'tool' +require 'tools/tool' class Slather < Tool diff --git a/analyzer/lib/tools/sonar_runner.rb b/analyzer/lib/tools/sonar_runner.rb index 3412ccb2..368eecbd 100644 --- a/analyzer/lib/tools/sonar_runner.rb +++ b/analyzer/lib/tools/sonar_runner.rb @@ -1,4 +1,4 @@ -require 'tool' +require 'tools/tool' class SonarRunner < Tool def self.command diff --git a/analyzer/lib/tools/sonar_scanner.rb b/analyzer/lib/tools/sonar_scanner.rb index b39c19bd..5b586020 100644 --- a/analyzer/lib/tools/sonar_scanner.rb +++ b/analyzer/lib/tools/sonar_scanner.rb @@ -1,4 +1,4 @@ -require 'tool' +require 'tools/tool' class SonarScanner < Tool def self.command diff --git a/analyzer/lib/tools/swiftlint.rb b/analyzer/lib/tools/swiftlint.rb index 50a39a04..589a712a 100644 --- a/analyzer/lib/tools/swiftlint.rb +++ b/analyzer/lib/tools/swiftlint.rb @@ -1,4 +1,4 @@ -require 'tool' +require 'tools/tool' # SwiftLint checks code style and conventions. # diff --git a/analyzer/lib/tools/tool.rb b/analyzer/lib/tools/tool.rb index 21d970e9..19b5c8c5 100644 --- a/analyzer/lib/tools/tool.rb +++ b/analyzer/lib/tools/tool.rb @@ -1,5 +1,5 @@ -require '../logging' -require '../canfail' +require 'logging' +require 'canfail' # A base class for tool wrappers. # diff --git a/analyzer/lib/tools/unit_tests.rb b/analyzer/lib/tools/unit_tests.rb index 26c3d03f..dc002a2f 100644 --- a/analyzer/lib/tools/unit_tests.rb +++ b/analyzer/lib/tools/unit_tests.rb @@ -1,4 +1,4 @@ -require 'tool' +require 'tools/tool' # Runs unit tests using Xcode with `xcodebuild` class UnitTests < Tool From f680fe505e3508557bf266451f4c7fa6c64d9e86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gae=CC=88l=20Foppolo?= Date: Sun, 8 Sep 2019 18:56:13 +0200 Subject: [PATCH 27/30] Add executable --- analyzer/analyzer.gemspec | 2 +- analyzer/bin/analyzer | 3 +++ analyzer/lib/analyzer.rb | 4 +--- 3 files changed, 5 insertions(+), 4 deletions(-) create mode 100644 analyzer/bin/analyzer diff --git a/analyzer/analyzer.gemspec b/analyzer/analyzer.gemspec index bd75a83c..3ed1cf54 100644 --- a/analyzer/analyzer.gemspec +++ b/analyzer/analyzer.gemspec @@ -9,7 +9,7 @@ Gem::Specification.new do |s| s.required_ruby_version = '>= 2.0.0' s.files = `git ls-files`.split($/) - #s.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } + s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) } s.require_paths = ["lib"] #s.add_runtime_dependency 'java-properties', "= 0.2.0" diff --git a/analyzer/bin/analyzer b/analyzer/bin/analyzer new file mode 100644 index 00000000..33d39460 --- /dev/null +++ b/analyzer/bin/analyzer @@ -0,0 +1,3 @@ +require 'analyzer' + +Analyzer.new.run \ No newline at end of file diff --git a/analyzer/lib/analyzer.rb b/analyzer/lib/analyzer.rb index 9d2033e7..324d6831 100644 --- a/analyzer/lib/analyzer.rb +++ b/analyzer/lib/analyzer.rb @@ -75,6 +75,4 @@ def reporter end -end - -Analyzer.new.run \ No newline at end of file +end \ No newline at end of file From f67f6bc5a158bdd5631c8e33a5055fc240f8e630 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gae=CC=88l=20Foppolo?= Date: Sun, 8 Sep 2019 19:19:35 +0200 Subject: [PATCH 28/30] Fix executable and add version --- analyzer/Gemfile | 4 ++-- analyzer/analyzer.gemspec | 15 ++++++++++----- analyzer/bin/analyzer | 2 ++ analyzer/lib/version.rb | 3 +++ 4 files changed, 17 insertions(+), 7 deletions(-) mode change 100644 => 100755 analyzer/bin/analyzer create mode 100644 analyzer/lib/version.rb diff --git a/analyzer/Gemfile b/analyzer/Gemfile index ada58715..f897cf0e 100644 --- a/analyzer/Gemfile +++ b/analyzer/Gemfile @@ -1,5 +1,5 @@ source 'https://rubygems.org' -gem 'java-properties', "= 0.2.0" +gemspec + gem 'xcpretty', "= 0.2.2", git: "https://github.com/Backelite/xcpretty" -gem 'slather', "= 2.4.7" \ No newline at end of file diff --git a/analyzer/analyzer.gemspec b/analyzer/analyzer.gemspec index 3ed1cf54..3a70cfd9 100644 --- a/analyzer/analyzer.gemspec +++ b/analyzer/analyzer.gemspec @@ -1,19 +1,24 @@ +lib = File.expand_path('../lib', __FILE__) +$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) +require 'version' + Gem::Specification.new do |s| s.name = "analyzer" - s.version = "0.0.1" + s.version = AnalyzerV::VERSION s.summary = "SonarSwift plugin analyzer" s.authors = ["Gaël FOppolo"] - s.description = "SonarSwift plugin analyzer" + s.description = "SonarSwift plugin analyzer" s.license = 'MIT' + s.required_ruby_version = '>= 2.0.0' s.files = `git ls-files`.split($/) s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) } s.require_paths = ["lib"] - #s.add_runtime_dependency 'java-properties', "= 0.2.0" - #s.add_runtime_dependency 'xcpretty', "= 0.2.2", git: "https://github.com/Backelite/xcpretty" - #s.add_runtime_dependency 'slather', "= 2.4.7" + s.add_runtime_dependency 'java-properties', "= 0.2.0" + s.add_runtime_dependency 'slather', "= 2.4.7" + s.add_runtime_dependency 'xcpretty', "= 0.3.0" end \ No newline at end of file diff --git a/analyzer/bin/analyzer b/analyzer/bin/analyzer old mode 100644 new mode 100755 index 33d39460..9ddaea74 --- a/analyzer/bin/analyzer +++ b/analyzer/bin/analyzer @@ -1,3 +1,5 @@ +#!/usr/bin/env ruby + require 'analyzer' Analyzer.new.run \ No newline at end of file diff --git a/analyzer/lib/version.rb b/analyzer/lib/version.rb new file mode 100644 index 00000000..b552c37b --- /dev/null +++ b/analyzer/lib/version.rb @@ -0,0 +1,3 @@ +module AnalyzerV + VERSION = "0.0.1" +end From 78c472c430cce3fc29f99632af750e46884b42aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gae=CC=88l=20Foppolo?= Date: Sun, 8 Sep 2019 19:25:09 +0200 Subject: [PATCH 29/30] Remove xcpretty fork --- analyzer/Gemfile | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/analyzer/Gemfile b/analyzer/Gemfile index f897cf0e..cd8aa9e0 100644 --- a/analyzer/Gemfile +++ b/analyzer/Gemfile @@ -1,5 +1,3 @@ source 'https://rubygems.org' -gemspec - -gem 'xcpretty', "= 0.2.2", git: "https://github.com/Backelite/xcpretty" +gemspec \ No newline at end of file From 6becc6b85ea15946e46791da151c2f041d815888 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gae=CC=88l=20Foppolo?= Date: Sun, 8 Sep 2019 20:33:22 +0200 Subject: [PATCH 30/30] Fix gemspec and add a quick README --- analyzer/README.md | 33 +++++++++++++++++++++++++++++++++ analyzer/analyzer.gemspec | 4 ++-- 2 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 analyzer/README.md diff --git a/analyzer/README.md b/analyzer/README.md new file mode 100644 index 00000000..dc40239a --- /dev/null +++ b/analyzer/README.md @@ -0,0 +1,33 @@ +# README + +# Installation + +```sh +gem build analyzer.gemspec --output=analyzer.gem +``` +```sh +gem install analyzer.gem +``` + +# Usage + +```sh +analyzer +``` + +To see available options: `analyzer -h` + +# Requirements + +* Xcode +* XCPretty +* Slather +* SwiftLint +* Lizard +* OCLint +* FauxPas +* SonarScanner + +## Behavior + +When a tool is not installed, the analyzer will gracefully skip it. \ No newline at end of file diff --git a/analyzer/analyzer.gemspec b/analyzer/analyzer.gemspec index 3a70cfd9..704c82e5 100644 --- a/analyzer/analyzer.gemspec +++ b/analyzer/analyzer.gemspec @@ -3,10 +3,10 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) require 'version' Gem::Specification.new do |s| - s.name = "analyzer" + s.name = "sonar-swift-analyzer" s.version = AnalyzerV::VERSION s.summary = "SonarSwift plugin analyzer" - s.authors = ["Gaël FOppolo"] + s.authors = ["Gaël Foppolo"] s.description = "SonarSwift plugin analyzer" s.license = 'MIT'