lib/quality/rake/task.rb in quality-1.0.0 vs lib/quality/rake/task.rb in quality-1.1.0
- old
+ new
@@ -1,17 +1,16 @@
#!/usr/bin/env ruby
require 'rake'
require 'rake/tasklib'
require 'rbconfig'
+require_relative '../quality_checker'
module Quality
#
# Defines a task library for running quality's various tools
- # (Classes here will be configured via the Rakefile, and therefore will
- # possess a :reek:attribute or two.)
#
module Rake
# A Rake task that run quality tools on a set of source files, and
# enforce a ratcheting quality level.
@@ -24,11 +23,10 @@
# end
#
# This will create a task that can be run with:
#
# rake quality
- #
class Task < ::Rake::TaskLib
# Name of quality task.
# Defaults to :quality.
attr_accessor :quality_name
@@ -60,237 +58,206 @@
@ratchet_name = args[:ratchet_name] || 'ratchet'
# allow unit tests to override the class that Rake DSL
# messages are sent to.
- @dsl = args[:dsl]
+ @dsl = args[:dsl] || ::Rake::Task
# likewise, but for system()
@cmd_runner = args[:cmd_runner] || Kernel
- # likewise, but for IO.popen()
- @popener = args[:popener] || IO
-
# likewise, but for File.open() on the count files
@count_file = args[:count_file] || File
# likewise, but for IO.read()/IO.exist? on the count files
@count_io = args[:count_io] || IO
# likewise, but for Dir.glob() on target Ruby files
@globber = args[:globber] || Dir
+ # likewise, but for checking whether a gem is installed
+ @gem_spec = args[:gem_spec] || Gem::Specification
+
# uses exist?() and open() to write out configuration files
# for tools if needed (e.g., .cane file)
@configuration_writer = args[:configuration_writer] || File
- @skip_tools = [] if @skip_tools.nil?
- @config_files = nil
- @source_files = nil
- @ruby_opts = []
- @reek_opts = ''
- @fail_on_error = true
- @sort = nil
+ # Class which actually runs the quality check commands
+ @quality_checker_class =
+ args[:quality_checker_class] || Quality::QualityChecker
+ @skip_tools = []
+
+ @output_dir = '.'
+
yield self if block_given?
- @config_files ||= 'config/**/*.reek'
- @source_files ||= 'lib/**/*.rb'
- @output_dir ||= "."
+
define
end
- private
+ private
def define # :nodoc:
desc 'Verify quality has increased or stayed ' +
'the same' unless ::Rake.application.last_comment
- if @dsl.nil?
- task(quality_name) { run_quality }
- task(ratchet_name) { run_ratchet }
- else
- @dsl.task(quality_name) { run_quality }
- @dsl.task(ratchet_name) { run_ratchet }
- end
+ @dsl.define_task(quality_name) { run_quality }
+ @dsl.define_task(ratchet_name) { run_ratchet }
end
def run_quality
tools = ['cane', 'flog', 'flay', 'reek', 'rubocop']
tools.each do |tool|
- installed = Gem::Specification.find_all_by_name(tool).any?
- suppressed = @skip_tools.include? tool
+ run_quality_with_tool(tool)
+ end
+ end
- if !installed
- puts "#{tool} not installed"
- elsif suppressed
- puts "Suppressing use of #{tool}"
- else
- method("quality_#{tool}".to_sym).call
- end
+ def run_quality_with_tool(tool)
+ installed = @gem_spec.find_all_by_name(tool).any?
+ suppressed = @skip_tools.include? tool
+
+ if !installed
+ puts "#{tool} not installed"
+ elsif suppressed
+ puts "Suppressing use of #{tool}"
+ else
+ method("quality_#{tool}".to_sym).call
end
end
def run_ratchet
- @globber.glob("*_high_water_mark").each { |filename|
- puts "Processing #{filename}"
- existing_violations = @count_io.read(filename).to_i
- if existing_violations < 0
- raise "Problem with file #{filename}"
- end
- new_violations = [0, existing_violations - 1].max
- @count_file.open(filename, 'w') {|f| f.write(new_violations.to_s) }
- if new_violations != existing_violations
- @cmd_runner.system("git commit -m 'tighten quality standard' #{filename}")
- end
- }
+ @globber.glob('*_high_water_mark').each do |filename|
+ run_ratchet_on_file(filename)
+ end
end
- def ratchet_quality_cmd(cmd,
- options,
- &process_output_line)
+ def run_ratchet_on_file(filename)
+ puts "Processing #{filename}"
+ existing_violations = count_existing_violations(filename)
+ new_violations = [0, existing_violations - 1].max
+ write_violations(filename, new_violations)
+ tighten_standard(filename) if new_violations != existing_violations
+ end
- gives_error_code_on_violations ||= options[:gives_error_code_on_violations]
-
- args ||= options[:args]
- emacs_format ||= options[:emacs_format]
-
- violations = 0
- out = ""
- found_output = false
- if defined?(RUBY_ENGINE) && (RUBY_ENGINE == 'jruby')
- full_cmd = "jruby -S #{cmd}"
- elsif RbConfig::CONFIG['host_os'] =~ /mswin|mingw/
- full_cmd = "#{cmd}.bat"
- else
- full_cmd = cmd
+ def write_violations(filename, new_violations)
+ @count_file.open(filename, 'w') do |file|
+ file.write(new_violations.to_s)
end
+ end
- if !args.nil?
- full_cmd = "#{full_cmd} #{args}"
- end
+ def count_existing_violations(filename)
+ existing_violations = @count_io.read(filename).to_i
+ fail("Problem with file #{filename}") if existing_violations < 0
+ existing_violations
+ end
- @popener.popen(full_cmd) do |f|
- while line = f.gets
- if emacs_format
- if line =~ /^ *(\S*.rb:[0-9]*) *(.*)/
- out << $1 << ": " << $2 << "\n"
- elsif line =~ /^ *(.*) +(\S*.rb:[0-9]*) *(.*)/
- out << $2 << ": " << $1 << "\n"
- else
- out << line
- end
- else
- out << line
- end
- found_output = true
- violations += yield line
- end
- end
- exit_status = $?.exitstatus
- if !gives_error_code_on_violations
- if exit_status != 0
- fail "Error detected running #{full_cmd}. Exit status is #{exit_status}, output is [#{out}]"
- end
- end
- filename = File.join(@output_dir, "#{cmd}_high_water_mark")
- if @count_file.exist?(filename)
- existing_violations = @count_io.read(filename).to_i
- else
- existing_violations = 9999999999
- end
- puts "Existing violations: #{existing_violations}"
- puts "Found #{violations} #{cmd} violations"
- if violations > existing_violations
- fail "Output from #{cmd}\n\n#{out}\n\n" +
- "Reduce total number of #{cmd} violations to #{existing_violations} or below!"
- elsif violations < existing_violations
- puts "Ratcheting quality up..."
- @count_file.open(filename, 'w') do |f|
- f.write(violations.to_s)
- end
- end
+ def tighten_standard(filename)
+ @cmd_runner
+ .system("git commit -m 'tighten quality standard' #{filename}")
end
+ def ratchet_quality_cmd(cmd,
+ command_options,
+ &count_violations_on_line)
+ quality_checker = @quality_checker_class.new(cmd,
+ command_options,
+ @output_dir)
+ quality_checker.execute(&count_violations_on_line)
+ end
+
def quality_cane
- if ! @configuration_writer.exist?(".cane")
- @configuration_writer.open(".cane", "w") {|f| f.write("-f **/*.rb")}
+ unless @configuration_writer.exist?('.cane')
+ @configuration_writer.open('.cane', 'w') do |file|
+ file.write('-f **/*.rb')
+ end
end
- ratchet_quality_cmd("cane",
+ ratchet_quality_cmd('cane',
gives_error_code_on_violations: true,
- emacs_format: true) { |line|
+ emacs_format: true) do |line|
if line =~ /\(([0-9]*)\):$/
$1.to_i
else
0
end
- }
+ end
end
def ruby_dirs
@ruby_dirs ||= %w{lib test features}
end
def ruby_files
- @globber.glob('*.rb').concat(@globber.glob(File.join("{#{ruby_dirs.join(',')}}", '**', '*.rb'))).join(' ')
+ @globber.glob('*.rb')
+ .concat(@globber.glob(File.join("{#{ruby_dirs.join(',')}}",
+ '**', '*.rb'))).join(' ')
end
def quality_reek
- args = "--line-number #{ruby_files}"
- ratchet_quality_cmd("reek",
+ args = "--single-line #{ruby_files}"
+ ratchet_quality_cmd('reek',
args: args,
emacs_format: true,
- gives_error_code_on_violations: true) { |line|
- if line =~ /^ .* (.*)$/
- 1
- else
- 0
- end
- }
+ gives_error_code_on_violations: true) do |line|
+ self.class.count_reek_violations(line)
+ end
end
+ def self.count_reek_violations(line)
+ if line =~ /^ .* (.*)$/
+ 1
+ else
+ 0
+ end
+ end
+
def quality_flog
- threshold = 50
- ratchet_quality_cmd("flog",
- args: "--all --continue --methods-only #{ruby_files}",
- emacs_format: true) { |line|
- if line =~ /^ *([0-9.]*): flog total$/
- 0
- #$1.to_i
- elsif line =~ /^ *([0-9.]*): (.*) .*.rb:[0-9]*$/
- score = $1.to_i
- if score > threshold
- 1
- else
- 0
- end
+ ratchet_quality_cmd('flog',
+ args: "--all --continue --methods-only #{ruby_files}",
+ emacs_format: true) do |line|
+ self.class.count_violations_in_flog_output(line)
+ end
+ end
+
+ def self.count_violations_in_flog_output(line, threshold = 50)
+ if line =~ /^ *([0-9.]*): flog total$/
+ 0
+ elsif line =~ /^ *([0-9.]*): (.*) .*.rb:[0-9]*$/
+ score = $1.to_i
+ if score > threshold
+ 1
else
0
end
- }
+ else
+ 0
+ end
end
def quality_flay
- ratchet_quality_cmd("flay",
+ ratchet_quality_cmd('flay',
args: "-m 75 -t 99999 #{ruby_files}",
- emacs_format: true) { |line|
+ emacs_format: true) do |line|
if line =~ /^[0-9]*\).* \(mass = ([0-9]*)\)$/
$1.to_i
else
0
end
- }
+ end
end
def quality_rubocop
- ratchet_quality_cmd("rubocop",
+ ratchet_quality_cmd('rubocop',
gives_error_code_on_violations: true,
- args: "--format emacs #{ruby_files}") { |line|
- if line =~ /^.* file[s|] inspected, (.*) offence[s|] detected$/
- 0
- else
- 1
- end
- }
+ args: "--format emacs #{ruby_files}") do |line|
+ self.class.count_rubocop_violations(line)
+ end
end
+ def self.count_rubocop_violations(line)
+ if line =~ /^.* file[s|] inspected, (.*) offence[s|] detected$/
+ 0
+ else
+ 1
+ end
+ end
end
end
end