Skip to content

Commit

Permalink
Added masked smells to report headers
Browse files Browse the repository at this point in the history
  • Loading branch information
kevinrutherford committed Jul 6, 2009
1 parent db1985a commit 079dca3
Show file tree
Hide file tree
Showing 9 changed files with 84 additions and 25 deletions.
2 changes: 2 additions & 0 deletions Manifest.txt
Expand Up @@ -16,6 +16,8 @@ lib/reek/block_context.rb
lib/reek/class_context.rb
lib/reek/code_context.rb
lib/reek/code_parser.rb
lib/reek/config_file.rb
lib/reek/detector_stack.rb
lib/reek/exceptions.reek
lib/reek/if_context.rb
lib/reek/method_context.rb
Expand Down
4 changes: 2 additions & 2 deletions features/masking_smells.feature
Expand Up @@ -22,7 +22,7 @@ Feature: Masking smells using config files
Scenario: corrupt config file prevents normal output
When I run reek spec/samples/corrupt_config_file/dirty.rb
Then it fails with exit status 1
And it reports the error 'Error: invalid configuration file "corrupt.reek"'
And it reports the error 'Error: Invalid configuration file "corrupt.reek" -- not a Hash'

Scenario: missing source file is an error
When I run reek no_such_file.rb
Expand All @@ -34,7 +34,7 @@ Feature: Masking smells using config files
Then it fails with exit status 2
And it reports:
"""
spec/samples/masked/dirty.rb -- 3 warnings:
spec/samples/masked/dirty.rb -- 3 warnings (+3 masked):
Dirty#a calls @s.title multiple times (Duplication)
Dirty#a calls puts(@s.title) multiple times (Duplication)
Dirty#a/block/block is nested (Nested Iterators)
Expand Down
31 changes: 31 additions & 0 deletions lib/reek/config_file.rb
@@ -0,0 +1,31 @@
require 'yaml'

module Reek
class ConfigFile

def initialize(file_path)
@file_path = file_path
@hash = YAML.load_file(@file_path) || {}
problem('not a Hash') unless Hash === @hash
end

#
# Configure the given sniffer using the contents of the config file.
#
def configure(sniffer)
@hash.each { |klass_name, config|
sniffer.configure(find_class(klass_name), config)
}
end

def find_class(name)
klass = Reek::Smells.const_get(name)
problem("#{name} is not a code smell") unless klass
klass
end

def problem(reason)
raise "Invalid configuration file \"#{File.basename(@file_path)}\" -- #{reason}"
end
end
end
24 changes: 24 additions & 0 deletions lib/reek/detector_stack.rb
@@ -0,0 +1,24 @@

module Reek
class DetectorStack

def initialize(default_detector)
@detectors = [default_detector]
end

def push(config)
det = @detectors[0].copy
det.configure_with(config)
@detectors.each {|smell| smell.be_masked}
@detectors << det
end

def listen_to(hooks)
@detectors.each { |smell| smell.listen_to(hooks) }
end

def report_on(report)
@detectors.each { |smell| smell.report_on(report) }
end
end
end
2 changes: 1 addition & 1 deletion lib/reek/object_source.rb
Expand Up @@ -22,7 +22,7 @@ def self.unify(sexp) # :nodoc:

def initialize(code, desc) # :nodoc:
super
@sniffer.disable('LargeClass')
@sniffer.disable(LargeClass)
end

def can_parse_objects?
Expand Down
2 changes: 1 addition & 1 deletion lib/reek/smells/long_parameter_list.rb
Expand Up @@ -22,7 +22,7 @@ def self.default_config
super.adopt(MAX_ALLOWED_PARAMS_KEY => 3)
end

def initialize(config)
def initialize(config = LongParameterList.default_config)
super(config)
@action = 'has'
end
Expand Down
2 changes: 1 addition & 1 deletion lib/reek/smells/long_yield_list.rb
Expand Up @@ -9,7 +9,7 @@ def self.contexts # :nodoc:
[:yield]
end

def initialize(config)
def initialize(config = LongYieldList.default_config)
super
@action = 'yields'
end
Expand Down
8 changes: 6 additions & 2 deletions lib/reek/smells/smell_detector.rb
Expand Up @@ -40,16 +40,20 @@ def self.create(config)

def self.listen(hooks, config)
detector = create(config)
contexts.each { |ctx| hooks[ctx] << detector }
detector.listen_to(hooks)
detector
end

def initialize(config)
def initialize(config = SmellDetector.default_config)
@config = config
@smells_found = []
@masked = false
end

def listen_to(hooks)
self.class.contexts.each { |ctx| hooks[ctx] << self }
end

def be_masked
@masked = true
end
Expand Down
34 changes: 16 additions & 18 deletions lib/reek/sniffer.rb
@@ -1,3 +1,4 @@
require 'reek/detector_stack'
require 'reek/smells/control_couple'
require 'reek/smells/duplication'
require 'reek/smells/feature_envy'
Expand All @@ -8,6 +9,7 @@
require 'reek/smells/nested_iterators'
require 'reek/smells/uncommunicative_name'
require 'reek/smells/utility_function'
require 'reek/config_file'
require 'yaml'

class Hash
Expand Down Expand Up @@ -55,7 +57,9 @@ class Sniffer
def initialize
defaults_file = File.join(File.dirname(__FILE__), '..', '..', 'config', 'defaults.reek')
@config = YAML.load_file(defaults_file)
@detectors = nil
@typed_detectors = nil
@detectors = Hash.new
SMELL_CLASSES.each { |klass| @detectors[klass] = DetectorStack.new(klass.new) }
@listeners = []
end

Expand All @@ -67,27 +71,21 @@ def initialize
#
def configure_along_path(filename)
path = File.expand_path(File.dirname(filename))
all_reekfiles(path).each { |rfile| configure_with(rfile) }
all_reekfiles(path).each { |config_file| ConfigFile.new(config_file).configure(self) }
self
end

#
# Overrides this sniffer's current settings with those in the named
# +config_file+.
#
def configure_with(config_file)
hash = YAML.load_file(config_file)
return unless hash
raise "invalid configuration file \"#{File.basename(config_file)}\"" unless Hash === hash
hash.push_keys(@config)
def configure(klass, config)
@detectors[klass].push(config)
end

def disable(smell)
@config[smell].adopt!({Reek::Smells::SmellDetector::ENABLED_KEY => false})
def disable(klass)
disabled_config = {Reek::Smells::SmellDetector::ENABLED_KEY => false}
@detectors[klass].push(disabled_config)
end

def report_on(report)
@listeners.each {|smell| smell.report_on(report)}
@detectors.each_value { |stack| stack.report_on(report) }
end

def examine(scope, type)
Expand All @@ -98,11 +96,11 @@ def examine(scope, type)
private

def smell_listeners()
unless @detectors
@detectors = Hash.new {|hash,key| hash[key] = [] }
SMELL_CLASSES.each { |smell| @listeners << smell.listen(@detectors, @config) }
unless @typed_detectors
@typed_detectors = Hash.new {|hash,key| hash[key] = [] }
@detectors.each_value { |stack| stack.listen_to(@typed_detectors) }
end
@detectors
@typed_detectors
end

def all_reekfiles(path)
Expand Down

0 comments on commit 079dca3

Please sign in to comment.