forked from troessner/reek
-
Notifications
You must be signed in to change notification settings - Fork 0
/
sniffer.rb
113 lines (98 loc) · 2.88 KB
/
sniffer.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
require 'reek/detector_stack'
require 'reek/smells/control_couple'
require 'reek/smells/duplication'
require 'reek/smells/feature_envy'
require 'reek/smells/large_class'
require 'reek/smells/long_method'
require 'reek/smells/long_parameter_list'
require 'reek/smells/long_yield_list'
require 'reek/smells/nested_iterators'
require 'reek/smells/uncommunicative_name'
require 'reek/smells/utility_function'
require 'reek/config_file'
require 'yaml'
class Hash
def push_keys(hash)
keys.each {|key| hash[key].adopt!(self[key]) }
end
def adopt!(other)
other.keys.each do |key|
ov = other[key]
if Array === ov and has_key?(key)
self[key] += ov
else
self[key] = ov
end
end
self
end
def adopt(other)
self.deep_copy.adopt!(other)
end
def deep_copy
YAML::load(YAML::dump(self))
end
end
module Reek
class Sniffer
SMELL_CLASSES = [
Smells::ControlCouple,
Smells::Duplication,
Smells::FeatureEnvy,
Smells::LargeClass,
Smells::LongMethod,
Smells::LongParameterList,
Smells::LongYieldList,
Smells::NestedIterators,
Smells::UncommunicativeName,
Smells::UtilityFunction,
]
def initialize
defaults_file = File.join(File.dirname(__FILE__), '..', '..', 'config', 'defaults.reek')
@config = YAML.load_file(defaults_file)
@typed_detectors = nil
@detectors = Hash.new
SMELL_CLASSES.each { |klass| @detectors[klass] = DetectorStack.new(klass.new) }
@listeners = []
end
#
# Configures this sniffer using any *.reek config files found
# on the path to the named file. Config files are applied in order,
# "root-first", so that config files closer to the named file override
# those further up the path.
#
def configure_along_path(filename)
path = File.expand_path(File.dirname(filename))
all_reekfiles(path).each { |config_file| ConfigFile.new(config_file).configure(self) }
self
end
def configure(klass, config)
@detectors[klass].push(config)
end
def disable(klass)
disabled_config = {Reek::Smells::SmellDetector::ENABLED_KEY => false}
@detectors[klass].push(disabled_config)
end
def report_on(report)
@detectors.each_value { |stack| stack.report_on(report) }
end
def examine(scope, type)
listeners = smell_listeners[type]
listeners.each {|smell| smell.examine(scope) } if listeners
end
private
def smell_listeners()
unless @typed_detectors
@typed_detectors = Hash.new {|hash,key| hash[key] = [] }
@detectors.each_value { |stack| stack.listen_to(@typed_detectors) }
end
@typed_detectors
end
def all_reekfiles(path)
return [] unless File.exist?(path)
parent = File.dirname(path)
return [] if path == parent
all_reekfiles(parent) + Dir["#{path}/*.reek"]
end
end
end