Skip to content

Instantly share code, notes, and snippets.

@r10r
Created July 29, 2013 21:01
Show Gist options
  • Save r10r/6107794 to your computer and use it in GitHub Desktop.
Save r10r/6107794 to your computer and use it in GitHub Desktop.
Reek checkstyle formatter
require 'reek/rake/task'
require 'syspect/rspec/reek_checkstyle_formatter'
Reek::Rake::Task.new do |t|
t.fail_on_error = false
t.reek_opts = '-y -n'
end
namespace :reek do
desc 'Generate checkstyle report for code smells analyzed by reek.'
task :checkstyle do
# see https://github.com/troessner/reek/wiki/Basic-Smell-Options
ReekCheckstyleFormatter.new.run
end
end
require 'reek/source/source_locator'
require 'reek/examiner'
require 'rexml/document'
require 'pathname'
class ReekCheckstyleFormatter
REXML_PRETTY_PRINT_INDENT = 0
class << self
attr_accessor :glob_pattern, :output, :smell_doc_url, :skip_disabled, :project_dir
end
@glob_pattern = 'lib/**/*.rb'
@output = 'spec/reports/reek_checkstyle.xml'
@smell_doc_url = 'https://github.com/troessner/reek/wiki'
@skip_disabled = true
@project_dir = Dir.pwd
def initialize(options = {})
@glob_pattern = options[:glob_pattern] || self.class.glob_pattern
@output = options[:output] || self.class.output
@smell_doc_url = options[:smell_doc_url] || self.class.smell_doc_url
@skip_disabled = options[:skip_disabled] || self.class.skip_disabled
@project_dir = options[:project_dir] || self.class.project_dir
end
def run
files = Dir.glob(@glob_pattern)
sources = Reek::Source::SourceLocator.new(files).all_sources
examined_files = sources.map {|src| Reek::Examiner.new(src, []) }
document = to_checkstyle(examined_files)
Pathname.new(@output).dirname.mkpath
File.open(@output, 'w+') do |file|
document.write(file, REXML_PRETTY_PRINT_INDENT)
end
end
def to_checkstyle(examined_files)
REXML::Document.new.tap do |document_node|
document_node << REXML::XMLDecl.new
REXML::Element.new('checkstyle', document_node).tap do |checkstyle_node|
examined_files.each do |examined_file|
add_file(checkstyle_node, examined_file)
end
end
end
end
def add_file(checkstyle_node, examined_file)
if examined_file.smells.length > 0
REXML::Element.new('file', checkstyle_node).tap do |file_node|
file_node.attributes['name'] = File.join(@project_dir, examined_file.description)
examined_file.smells.each do |smell|
if smell.status['is_active']
[*smell.location['lines']].each do |line|
add_smell(file_node, smell, line)
end
end
end
end
end
end
def add_smell(file_node, smell, line)
REXML::Element.new('error', file_node).tap do |error|
error.attributes['line'] = line
error.attributes['column'] = 0
error.attributes['severity'] = smell_severity(smell)
error.attributes['message'] = smell_message(smell)
#error.attributes['source'] = File.join(@project_dir, smell.source)
end
end
def smell_message(smell)
"<em>#{smell_anchor(smell)}</em> - #{smell.message}"
end
def smell_anchor(smell)
url = smell_url(smell)
"<a href='#{url}'>#{smell.smell['subclass']}</a>"
end
def smell_url(smell)
smell_page_name = (smell.smell['subclass']).scan(/[A-Z][^A-Z]*/).join('-')
[@smell_doc_url, smell_page_name].join("/")
end
def smell_severity(smell)
'warning'
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment