require 'pp'
require 'yaml'
require 'simplabs/excellent/parsing/parser'
require 'simplabs/excellent/parsing/code_processor'
module Simplabs
module Excellent
# The Runner is the interface to invoke parsing and processing of source code. You can pass either a String containing the code to process or the
# name of a file to read the code to process from.
class Runner
DEFAULT_CONFIG = {
:AssignmentInConditionalCheck => { },
:CaseMissingElseCheck => { },
:ClassLineCountCheck => { :threshold => 300 },
:ClassNameCheck => { :pattern => /^[A-Z][a-zA-Z0-9]*$/ },
:SingletonVariableCheck => { },
:CyclomaticComplexityBlockCheck => { :complexity => 4 },
:CyclomaticComplexityMethodCheck => { :complexity => 8 },
:EmptyRescueBodyCheck => { },
:ForLoopCheck => { },
:MethodLineCountCheck => { :line_count => 20 },
:MethodNameCheck => { :pattern => /^[_a-z<>=\[|+-\/\*`]+[_a-z0-9_<>=~@\[\]]*[=!\?]?$/ },
:ModuleLineCountCheck => { :line_count => 300 },
:ModuleNameCheck => { :pattern => /^[A-Z][a-zA-Z0-9]*$/ },
:ParameterNumberCheck => { :parameter_count => 3 },
:FlogMethodCheck => { },
:FlogBlockCheck => { },
:FlogClassCheck => { },
:'Rails::AttrProtectedCheck' => { },
:'Rails::AttrAccessibleCheck' => { }
}
attr_accessor :config #:nodoc:
# Initializes a Runner
#
# ==== Parameters
#
# * checks - The checks to apply - passed instances of the various check classes. If no checks are specified, all checks will be applied.
def initialize(*checks)
@config = DEFAULT_CONFIG
@checks = checks unless checks.empty?
@parser = Parsing::Parser.new
end
# Processes the +code+ and sets the file name of the warning to +filename+
#
# ==== Parameters
#
# * filename - The name of the file the code was read from.
# * code - The code to process (String).
def check(filename, code)
@checks ||= load_checks
@processor ||= Parsing::CodeProcessor.new(@checks)
node = parse(filename, code)
@processor.process(node)
end
# Processes the +code+, setting the file name of the warnings to '+dummy-file.rb+'
#
# ==== Parameters
#
# * code - The code to process (String).
def check_code(code)
check('dummy-file.rb', code)
end
# Processes the file +filename+. The code will be read from the file.
#
# ==== Parameters
#
# * filename - The name of the file to read the code from.
def check_file(filename)
check(filename, File.read(filename))
end
# Gets the warnings that were produced by the checks.
def warnings
@checks ||= []
@checks.collect { |check| check.warnings }.flatten
end
private
def parse(filename, code)
@parser.parse(code, filename)
end
def load_checks
check_objects = []
DEFAULT_CONFIG.each_pair do |key, value|
klass = eval("Simplabs::Excellent::Checks::#{key.to_s}")
check_objects << (value.empty? ? klass.new : klass.new(value))
end
check_objects
end
end
end
end