reek 1.2.6 → 1.2.7
Sign up to get free protection for your applications and to get access to all the features.
- data/.yardopts +10 -0
- data/History.txt +20 -0
- data/README.md +90 -0
- data/bin/reek +2 -2
- data/config/defaults.reek +34 -4
- data/features/masking_smells.feature +35 -15
- data/features/options.feature +2 -0
- data/features/rake_task.feature +11 -18
- data/features/reports.feature +13 -15
- data/features/samples.feature +90 -105
- data/features/stdin.feature +3 -6
- data/features/step_definitions/reek_steps.rb +8 -4
- data/features/support/env.rb +2 -3
- data/features/yaml.feature +124 -0
- data/lib/reek.rb +8 -4
- data/lib/reek/cli/application.rb +46 -0
- data/lib/reek/cli/command_line.rb +106 -0
- data/lib/reek/cli/help_command.rb +18 -0
- data/lib/reek/cli/reek_command.rb +37 -0
- data/lib/reek/cli/report.rb +91 -0
- data/lib/reek/cli/version_command.rb +19 -0
- data/lib/reek/cli/yaml_command.rb +32 -0
- data/lib/reek/core/block_context.rb +18 -0
- data/lib/reek/core/class_context.rb +23 -0
- data/lib/reek/core/code_context.rb +72 -0
- data/lib/reek/core/code_parser.rb +192 -0
- data/lib/reek/core/detector_stack.rb +29 -0
- data/lib/reek/core/masking_collection.rb +46 -0
- data/lib/reek/core/method_context.rb +132 -0
- data/lib/reek/core/module_context.rb +64 -0
- data/lib/reek/{object_refs.rb → core/object_refs.rb} +8 -6
- data/lib/reek/{singleton_method_context.rb → core/singleton_method_context.rb} +10 -5
- data/lib/reek/core/smell_configuration.rb +66 -0
- data/lib/reek/core/sniffer.rb +110 -0
- data/lib/reek/core/stop_context.rb +26 -0
- data/lib/reek/examiner.rb +88 -0
- data/lib/reek/rake/task.rb +124 -0
- data/lib/reek/smell_warning.rb +69 -13
- data/lib/reek/smells.rb +29 -0
- data/lib/reek/smells/attribute.rb +13 -14
- data/lib/reek/smells/boolean_parameter.rb +33 -0
- data/lib/reek/smells/class_variable.rb +8 -6
- data/lib/reek/smells/control_couple.rb +33 -17
- data/lib/reek/smells/data_clump.rb +10 -6
- data/lib/reek/smells/duplication.rb +24 -14
- data/lib/reek/smells/feature_envy.rb +11 -6
- data/lib/reek/smells/irresponsible_module.rb +28 -0
- data/lib/reek/smells/large_class.rb +9 -7
- data/lib/reek/smells/long_method.rb +6 -5
- data/lib/reek/smells/long_parameter_list.rb +11 -9
- data/lib/reek/smells/long_yield_list.rb +37 -7
- data/lib/reek/smells/nested_iterators.rb +34 -9
- data/lib/reek/smells/simulated_polymorphism.rb +15 -11
- data/lib/reek/smells/smell_detector.rb +24 -12
- data/lib/reek/smells/uncommunicative_method_name.rb +76 -0
- data/lib/reek/smells/uncommunicative_module_name.rb +76 -0
- data/lib/reek/smells/{uncommunicative_name.rb → uncommunicative_parameter_name.rb} +14 -26
- data/lib/reek/smells/uncommunicative_variable_name.rb +90 -0
- data/lib/reek/smells/utility_function.rb +33 -9
- data/lib/reek/source.rb +18 -0
- data/lib/reek/source/code_comment.rb +19 -0
- data/lib/reek/source/config_file.rb +72 -0
- data/lib/reek/source/core_extras.rb +46 -0
- data/lib/reek/source/sexp_formatter.rb +16 -0
- data/lib/reek/source/source_code.rb +44 -0
- data/lib/reek/source/source_file.rb +32 -0
- data/lib/reek/source/source_locator.rb +36 -0
- data/lib/reek/source/tree_dresser.rb +128 -0
- data/lib/reek/spec.rb +51 -0
- data/lib/reek/spec/should_reek.rb +34 -0
- data/lib/reek/spec/should_reek_of.rb +37 -0
- data/lib/reek/spec/should_reek_only_of.rb +36 -0
- data/reek.gemspec +5 -5
- data/spec/reek/{help_command_spec.rb → cli/help_command_spec.rb} +3 -4
- data/spec/reek/{reek_command_spec.rb → cli/reek_command_spec.rb} +8 -7
- data/spec/reek/cli/report_spec.rb +26 -0
- data/spec/reek/{version_command_spec.rb → cli/version_command_spec.rb} +3 -3
- data/spec/reek/cli/yaml_command_spec.rb +47 -0
- data/spec/reek/core/block_context_spec.rb +26 -0
- data/spec/reek/core/class_context_spec.rb +53 -0
- data/spec/reek/{code_context_spec.rb → core/code_context_spec.rb} +15 -37
- data/spec/reek/{code_parser_spec.rb → core/code_parser_spec.rb} +5 -5
- data/spec/reek/{config_spec.rb → core/config_spec.rb} +2 -6
- data/spec/reek/{masking_collection_spec.rb → core/masking_collection_spec.rb} +3 -4
- data/spec/reek/{method_context_spec.rb → core/method_context_spec.rb} +6 -7
- data/spec/reek/core/module_context_spec.rb +42 -0
- data/spec/reek/{object_refs_spec.rb → core/object_refs_spec.rb} +5 -6
- data/spec/reek/core/singleton_method_context_spec.rb +15 -0
- data/spec/reek/core/smell_configuration_spec.rb +11 -0
- data/spec/reek/core/stop_context_spec.rb +17 -0
- data/spec/reek/examiner_spec.rb +42 -0
- data/spec/reek/smell_warning_spec.rb +82 -33
- data/spec/reek/smells/attribute_spec.rb +33 -7
- data/spec/reek/smells/boolean_parameter_spec.rb +76 -0
- data/spec/reek/smells/class_variable_spec.rb +15 -6
- data/spec/reek/smells/control_couple_spec.rb +40 -29
- data/spec/reek/smells/data_clump_spec.rb +28 -7
- data/spec/reek/smells/duplication_spec.rb +47 -41
- data/spec/reek/smells/feature_envy_spec.rb +76 -18
- data/spec/reek/smells/irresponsible_module_spec.rb +37 -0
- data/spec/reek/smells/large_class_spec.rb +91 -56
- data/spec/reek/smells/long_method_spec.rb +32 -7
- data/spec/reek/smells/long_parameter_list_spec.rb +42 -13
- data/spec/reek/smells/long_yield_list_spec.rb +65 -0
- data/spec/reek/smells/nested_iterators_spec.rb +94 -3
- data/spec/reek/smells/simulated_polymorphism_spec.rb +48 -20
- data/spec/reek/smells/smell_detector_shared.rb +28 -0
- data/spec/reek/smells/uncommunicative_method_name_spec.rb +57 -0
- data/spec/reek/smells/uncommunicative_module_name_spec.rb +67 -0
- data/spec/reek/smells/uncommunicative_parameter_name_spec.rb +61 -0
- data/spec/reek/smells/uncommunicative_variable_name_spec.rb +124 -0
- data/spec/reek/smells/utility_function_spec.rb +45 -3
- data/spec/reek/source/code_comment_spec.rb +24 -0
- data/spec/reek/source/object_source_spec.rb +20 -0
- data/spec/reek/{adapters/source_spec.rb → source/source_code_spec.rb} +7 -8
- data/spec/reek/source/tree_dresser_spec.rb +165 -0
- data/spec/reek/spec/should_reek_of_spec.rb +76 -0
- data/spec/reek/spec/should_reek_only_of_spec.rb +89 -0
- data/spec/reek/{adapters → spec}/should_reek_spec.rb +8 -32
- data/spec/samples/all_but_one_masked/clean_one.rb +1 -0
- data/spec/samples/all_but_one_masked/dirty.rb +1 -0
- data/spec/samples/all_but_one_masked/masked.reek +5 -1
- data/spec/samples/clean_due_to_masking/clean_one.rb +1 -0
- data/spec/samples/clean_due_to_masking/clean_three.rb +1 -0
- data/spec/samples/clean_due_to_masking/clean_two.rb +1 -0
- data/spec/samples/clean_due_to_masking/dirty_one.rb +1 -1
- data/spec/samples/clean_due_to_masking/dirty_two.rb +1 -1
- data/spec/samples/clean_due_to_masking/masked.reek +5 -1
- data/spec/samples/corrupt_config_file/dirty.rb +1 -1
- data/spec/samples/empty_config_file/dirty.rb +2 -1
- data/spec/samples/exceptions.reek +1 -1
- data/spec/samples/masked/dirty.rb +2 -1
- data/spec/samples/masked/masked.reek +3 -1
- data/spec/samples/mixed_results/clean_one.rb +1 -0
- data/spec/samples/mixed_results/clean_three.rb +1 -0
- data/spec/samples/mixed_results/clean_two.rb +1 -0
- data/spec/samples/mixed_results/dirty_one.rb +1 -0
- data/spec/samples/mixed_results/dirty_two.rb +1 -0
- data/spec/samples/not_quite_masked/dirty.rb +2 -1
- data/spec/samples/not_quite_masked/masked.reek +1 -1
- data/spec/samples/overrides/masked/dirty.rb +2 -1
- data/spec/samples/overrides/masked/lower.reek +3 -1
- data/spec/samples/three_clean_files/clean_one.rb +1 -0
- data/spec/samples/three_clean_files/clean_three.rb +1 -0
- data/spec/samples/three_clean_files/clean_two.rb +1 -0
- data/spec/samples/two_smelly_files/dirty_one.rb +2 -1
- data/spec/samples/two_smelly_files/dirty_two.rb +2 -1
- data/spec/spec_helper.rb +1 -2
- data/tasks/reek.rake +2 -2
- data/tasks/test.rake +12 -3
- metadata +81 -62
- data/README.rdoc +0 -84
- data/lib/reek/adapters/application.rb +0 -46
- data/lib/reek/adapters/command_line.rb +0 -77
- data/lib/reek/adapters/config_file.rb +0 -31
- data/lib/reek/adapters/core_extras.rb +0 -64
- data/lib/reek/adapters/rake_task.rb +0 -121
- data/lib/reek/adapters/report.rb +0 -86
- data/lib/reek/adapters/source.rb +0 -72
- data/lib/reek/adapters/spec.rb +0 -133
- data/lib/reek/block_context.rb +0 -62
- data/lib/reek/class_context.rb +0 -41
- data/lib/reek/code_context.rb +0 -68
- data/lib/reek/code_parser.rb +0 -203
- data/lib/reek/configuration.rb +0 -57
- data/lib/reek/detector_stack.rb +0 -37
- data/lib/reek/help_command.rb +0 -14
- data/lib/reek/if_context.rb +0 -18
- data/lib/reek/masking_collection.rb +0 -33
- data/lib/reek/method_context.rb +0 -138
- data/lib/reek/module_context.rb +0 -49
- data/lib/reek/name.rb +0 -57
- data/lib/reek/reek_command.rb +0 -28
- data/lib/reek/sexp_formatter.rb +0 -10
- data/lib/reek/sniffer.rb +0 -177
- data/lib/reek/stop_context.rb +0 -35
- data/lib/reek/tree_dresser.rb +0 -82
- data/lib/reek/version_command.rb +0 -14
- data/lib/reek/yield_call_context.rb +0 -12
- data/spec/reek/adapters/report_spec.rb +0 -31
- data/spec/reek/adapters/should_reek_of_spec.rb +0 -138
- data/spec/reek/adapters/should_reek_only_of_spec.rb +0 -87
- data/spec/reek/block_context_spec.rb +0 -65
- data/spec/reek/class_context_spec.rb +0 -161
- data/spec/reek/configuration_spec.rb +0 -12
- data/spec/reek/if_context_spec.rb +0 -17
- data/spec/reek/module_context_spec.rb +0 -46
- data/spec/reek/name_spec.rb +0 -37
- data/spec/reek/object_source_spec.rb +0 -23
- data/spec/reek/singleton_method_context_spec.rb +0 -16
- data/spec/reek/smells/smell_detector_spec.rb +0 -36
- data/spec/reek/smells/uncommunicative_name_spec.rb +0 -146
- data/spec/reek/sniffer_spec.rb +0 -11
- data/spec/reek/stop_context_spec.rb +0 -33
- data/spec/reek/tree_dresser_spec.rb +0 -20
data/lib/reek/help_command.rb
DELETED
data/lib/reek/if_context.rb
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
require 'reek/code_context'
|
2
|
-
|
3
|
-
module Reek
|
4
|
-
class IfContext < CodeContext
|
5
|
-
attr_reader :if_expr
|
6
|
-
|
7
|
-
def initialize(outer, exp)
|
8
|
-
super
|
9
|
-
@name = ''
|
10
|
-
@scope_connector = ''
|
11
|
-
@if_expr = exp[1]
|
12
|
-
end
|
13
|
-
|
14
|
-
def tests_a_parameter?
|
15
|
-
@if_expr[0] == :lvar and has_parameter(@if_expr[1])
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
@@ -1,33 +0,0 @@
|
|
1
|
-
require 'set'
|
2
|
-
|
3
|
-
#
|
4
|
-
# A set of items that can be "masked" or "visible". If an item is added
|
5
|
-
# more than once, only the "visible" copy is retained.
|
6
|
-
#
|
7
|
-
class MaskingCollection
|
8
|
-
def initialize
|
9
|
-
@visible_items = SortedSet.new
|
10
|
-
@masked_items = SortedSet.new
|
11
|
-
end
|
12
|
-
def found_smell(item)
|
13
|
-
@visible_items.add(item)
|
14
|
-
@masked_items.delete(item) if @masked_items.include?(item)
|
15
|
-
end
|
16
|
-
def found_masked_smell(item)
|
17
|
-
@masked_items.add(item) unless @visible_items.include?(item)
|
18
|
-
end
|
19
|
-
def num_visible_items
|
20
|
-
@visible_items.length
|
21
|
-
end
|
22
|
-
def num_masked_items
|
23
|
-
@masked_items.length
|
24
|
-
end
|
25
|
-
def each_item(&blk)
|
26
|
-
all = SortedSet.new(@visible_items)
|
27
|
-
all.merge(@masked_items)
|
28
|
-
all.each(&blk)
|
29
|
-
end
|
30
|
-
def each_visible_item(&blk)
|
31
|
-
@visible_items.each(&blk)
|
32
|
-
end
|
33
|
-
end
|
data/lib/reek/method_context.rb
DELETED
@@ -1,138 +0,0 @@
|
|
1
|
-
require 'reek/name'
|
2
|
-
require 'reek/block_context'
|
3
|
-
require 'reek/object_refs'
|
4
|
-
|
5
|
-
class Array
|
6
|
-
def power_set
|
7
|
-
self.inject([[]]) { |cum, element| cum.cross(element) }
|
8
|
-
end
|
9
|
-
|
10
|
-
def bounded_power_set(lower_bound)
|
11
|
-
power_set.select {|ps| ps.length > lower_bound}
|
12
|
-
end
|
13
|
-
|
14
|
-
def cross(element)
|
15
|
-
result = []
|
16
|
-
self.each do |set|
|
17
|
-
result << set
|
18
|
-
result << (set + [element])
|
19
|
-
end
|
20
|
-
result
|
21
|
-
end
|
22
|
-
|
23
|
-
def intersection
|
24
|
-
self.inject { |res, elem| elem & res }
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
module Reek
|
29
|
-
|
30
|
-
module MethodParameters
|
31
|
-
def default_assignments
|
32
|
-
assignments = self[-1]
|
33
|
-
result = {}
|
34
|
-
return result unless is_assignment_block?(assignments)
|
35
|
-
assignments[1..-1].each do |exp|
|
36
|
-
result[exp[1]] = exp[2] if exp[0] == :lasgn
|
37
|
-
end
|
38
|
-
result
|
39
|
-
end
|
40
|
-
def is_arg?(param)
|
41
|
-
return false if is_assignment_block?(param)
|
42
|
-
return !(param.to_s =~ /^\&/)
|
43
|
-
end
|
44
|
-
def is_assignment_block?(param)
|
45
|
-
Array === param and param[0] == :block
|
46
|
-
end
|
47
|
-
|
48
|
-
def names
|
49
|
-
return @names if @names
|
50
|
-
@names = self[1..-1].select {|arg| is_arg?(arg)}.map {|arg| Name.new(arg)}
|
51
|
-
end
|
52
|
-
|
53
|
-
def length
|
54
|
-
names.length
|
55
|
-
end
|
56
|
-
|
57
|
-
def include?(name)
|
58
|
-
names.include?(name)
|
59
|
-
end
|
60
|
-
|
61
|
-
def to_s
|
62
|
-
"[#{names.map{|nm| nm.to_s}.join(', ')}]"
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
class MethodContext < VariableContainer
|
67
|
-
attr_reader :parameters
|
68
|
-
attr_reader :calls
|
69
|
-
attr_reader :refs
|
70
|
-
attr_reader :num_statements
|
71
|
-
|
72
|
-
def initialize(outer, exp)
|
73
|
-
# SMELL: Unused Parameter
|
74
|
-
super(outer, exp)
|
75
|
-
@parameters = exp[exp[0] == :defn ? 2 : 3] # SMELL: SimulatedPolymorphism
|
76
|
-
@parameters ||= []
|
77
|
-
@parameters.extend(MethodParameters)
|
78
|
-
@name = Name.new(exp[1])
|
79
|
-
@scope_connector = '#'
|
80
|
-
@num_statements = 0
|
81
|
-
@calls = Hash.new(0)
|
82
|
-
@depends_on_self = false
|
83
|
-
@refs = ObjectRefs.new
|
84
|
-
@outer.record_method(self) # SMELL: these could be found by tree walking
|
85
|
-
end
|
86
|
-
|
87
|
-
def count_statements(num)
|
88
|
-
@num_statements += num
|
89
|
-
end
|
90
|
-
|
91
|
-
def depends_on_instance?
|
92
|
-
@depends_on_self || is_overriding_method?(@name)
|
93
|
-
end
|
94
|
-
|
95
|
-
def has_parameter(sym)
|
96
|
-
@parameters.include?(sym.to_s)
|
97
|
-
end
|
98
|
-
|
99
|
-
def record_call_to(exp)
|
100
|
-
@calls[exp] += 1
|
101
|
-
record_receiver(exp)
|
102
|
-
end
|
103
|
-
|
104
|
-
def record_receiver(exp)
|
105
|
-
receiver, meth = exp[1..2]
|
106
|
-
receiver ||= [:self]
|
107
|
-
case receiver[0]
|
108
|
-
when :lvar
|
109
|
-
@refs.record_ref(receiver) unless meth == :new
|
110
|
-
when :self
|
111
|
-
record_use_of_self
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
def record_use_of_self
|
116
|
-
record_depends_on_self
|
117
|
-
@refs.record_reference_to_self
|
118
|
-
end
|
119
|
-
|
120
|
-
def record_instance_variable(sym)
|
121
|
-
record_use_of_self
|
122
|
-
@outer.record_instance_variable(sym)
|
123
|
-
end
|
124
|
-
|
125
|
-
def record_depends_on_self
|
126
|
-
@depends_on_self = true
|
127
|
-
end
|
128
|
-
|
129
|
-
def envious_receivers
|
130
|
-
return [] if @refs.self_is_max?
|
131
|
-
@refs.max_keys
|
132
|
-
end
|
133
|
-
|
134
|
-
def variable_names
|
135
|
-
@parameters.names + @local_variables.to_a
|
136
|
-
end
|
137
|
-
end
|
138
|
-
end
|
data/lib/reek/module_context.rb
DELETED
@@ -1,49 +0,0 @@
|
|
1
|
-
require 'reek/code_context'
|
2
|
-
require 'reek/code_parser'
|
3
|
-
require 'reek/sniffer'
|
4
|
-
|
5
|
-
module Reek
|
6
|
-
class ModuleContext < CodeContext
|
7
|
-
|
8
|
-
class << self
|
9
|
-
def create(outer, exp)
|
10
|
-
res = Name.resolve(exp[1], outer)
|
11
|
-
new(res[0], res[1], exp)
|
12
|
-
end
|
13
|
-
|
14
|
-
def from_s(src)
|
15
|
-
source = src.to_reek_source
|
16
|
-
sniffer = Sniffer.new(source)
|
17
|
-
CodeParser.new(sniffer).do_module_or_class(source.syntax_tree, self)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
def initialize(outer, name, exp)
|
22
|
-
super(outer, exp)
|
23
|
-
@name = name
|
24
|
-
@scope_connector = '::'
|
25
|
-
@parsed_methods = []
|
26
|
-
end
|
27
|
-
|
28
|
-
def myself
|
29
|
-
@myself ||= @outer.find_module(@name)
|
30
|
-
end
|
31
|
-
|
32
|
-
def find_module(modname)
|
33
|
-
return nil unless myself
|
34
|
-
@myself.const_or_nil(modname.to_s)
|
35
|
-
end
|
36
|
-
|
37
|
-
def parameterized_methods(min_clump_size)
|
38
|
-
@parsed_methods.select {|meth| meth.parameters.length >= min_clump_size }
|
39
|
-
end
|
40
|
-
|
41
|
-
def record_method(meth)
|
42
|
-
@parsed_methods << meth
|
43
|
-
end
|
44
|
-
|
45
|
-
def variable_names
|
46
|
-
[]
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
data/lib/reek/name.rb
DELETED
@@ -1,57 +0,0 @@
|
|
1
|
-
require 'ruby_parser'
|
2
|
-
|
3
|
-
module Reek
|
4
|
-
class Name
|
5
|
-
include Comparable
|
6
|
-
|
7
|
-
def self.resolve(exp, context)
|
8
|
-
unless Array === exp
|
9
|
-
return resolve_string(exp.to_s, context)
|
10
|
-
end
|
11
|
-
name = exp[1]
|
12
|
-
case exp[0]
|
13
|
-
when :colon2
|
14
|
-
return [resolve(name, context)[0], new(exp[2])]
|
15
|
-
when :const
|
16
|
-
return [ModuleContext.create(context, exp), new(name)]
|
17
|
-
when :colon3
|
18
|
-
return [StopContext.new, new(name)]
|
19
|
-
else
|
20
|
-
return [context, new(name)]
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
def self.resolve_string(str, context)
|
25
|
-
return [context, new(str)] unless str =~ /::/
|
26
|
-
resolve(RubyParser.new.parse(str), context)
|
27
|
-
end
|
28
|
-
|
29
|
-
def initialize(sym)
|
30
|
-
@name = sym.to_s
|
31
|
-
end
|
32
|
-
|
33
|
-
def hash # :nodoc:
|
34
|
-
@name.hash
|
35
|
-
end
|
36
|
-
|
37
|
-
def eql?(other)
|
38
|
-
self == other
|
39
|
-
end
|
40
|
-
|
41
|
-
def <=>(other) # :nodoc:
|
42
|
-
@name <=> other.to_s
|
43
|
-
end
|
44
|
-
|
45
|
-
def effective_name
|
46
|
-
@name.gsub(/^@*/, '')
|
47
|
-
end
|
48
|
-
|
49
|
-
def inspect
|
50
|
-
@name.inspect
|
51
|
-
end
|
52
|
-
|
53
|
-
def to_s
|
54
|
-
@name
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
data/lib/reek/reek_command.rb
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
require 'reek/sniffer'
|
2
|
-
|
3
|
-
module Reek
|
4
|
-
|
5
|
-
class ReekCommand
|
6
|
-
|
7
|
-
def initialize(sources, report_class, show_all)
|
8
|
-
@sniffer = sources.length > 0 ? sources.sniff : sniff_stdin
|
9
|
-
@report_class = report_class
|
10
|
-
@show_all = show_all
|
11
|
-
end
|
12
|
-
|
13
|
-
def sniff_stdin
|
14
|
-
Reek::Sniffer.new($stdin.to_reek_source('$stdin'))
|
15
|
-
end
|
16
|
-
|
17
|
-
def execute(view)
|
18
|
-
rpt = @report_class.new(@sniffer.sniffers, @show_all)
|
19
|
-
view.output(rpt.report)
|
20
|
-
if @sniffer.smelly?
|
21
|
-
view.report_smells
|
22
|
-
else
|
23
|
-
view.report_success
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
end
|
data/lib/reek/sexp_formatter.rb
DELETED
data/lib/reek/sniffer.rb
DELETED
@@ -1,177 +0,0 @@
|
|
1
|
-
require 'reek/detector_stack'
|
2
|
-
|
3
|
-
# SMELL: Duplication -- all these should be found automagically
|
4
|
-
require 'reek/smells/attribute'
|
5
|
-
require 'reek/smells/class_variable'
|
6
|
-
require 'reek/smells/control_couple'
|
7
|
-
require 'reek/smells/data_clump'
|
8
|
-
require 'reek/smells/duplication'
|
9
|
-
require 'reek/smells/feature_envy'
|
10
|
-
require 'reek/smells/large_class'
|
11
|
-
require 'reek/smells/long_method'
|
12
|
-
require 'reek/smells/long_parameter_list'
|
13
|
-
require 'reek/smells/long_yield_list'
|
14
|
-
require 'reek/smells/nested_iterators'
|
15
|
-
require 'reek/smells/simulated_polymorphism'
|
16
|
-
require 'reek/smells/uncommunicative_name'
|
17
|
-
require 'reek/smells/utility_function'
|
18
|
-
require 'reek/code_parser'
|
19
|
-
require 'yaml'
|
20
|
-
|
21
|
-
class Hash
|
22
|
-
def push_keys(hash)
|
23
|
-
keys.each {|key| hash[key].adopt!(self[key]) }
|
24
|
-
end
|
25
|
-
|
26
|
-
def adopt!(other)
|
27
|
-
other.keys.each do |key|
|
28
|
-
ov = other[key]
|
29
|
-
if Array === ov and has_key?(key)
|
30
|
-
self[key] += ov
|
31
|
-
else
|
32
|
-
self[key] = ov
|
33
|
-
end
|
34
|
-
end
|
35
|
-
self
|
36
|
-
end
|
37
|
-
|
38
|
-
def adopt(other)
|
39
|
-
self.deep_copy.adopt!(other)
|
40
|
-
end
|
41
|
-
|
42
|
-
def deep_copy
|
43
|
-
YAML::load(YAML::dump(self))
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
module Reek
|
48
|
-
class Sniffer
|
49
|
-
|
50
|
-
def self.smell_classes
|
51
|
-
# SMELL: Duplication -- these should be loaded by listing the files
|
52
|
-
[
|
53
|
-
Smells::Attribute,
|
54
|
-
Smells::ClassVariable,
|
55
|
-
Smells::ControlCouple,
|
56
|
-
Smells::DataClump,
|
57
|
-
Smells::Duplication,
|
58
|
-
Smells::FeatureEnvy,
|
59
|
-
Smells::LargeClass,
|
60
|
-
Smells::LongMethod,
|
61
|
-
Smells::LongParameterList,
|
62
|
-
Smells::LongYieldList,
|
63
|
-
Smells::NestedIterators,
|
64
|
-
Smells::SimulatedPolymorphism,
|
65
|
-
Smells::UncommunicativeName,
|
66
|
-
Smells::UtilityFunction,
|
67
|
-
]
|
68
|
-
end
|
69
|
-
|
70
|
-
def initialize(src)
|
71
|
-
@already_checked_for_smells = false
|
72
|
-
@typed_detectors = nil
|
73
|
-
@detectors = Hash.new
|
74
|
-
Sniffer.smell_classes.each { |klass| @detectors[klass] = DetectorStack.new(klass.new) }
|
75
|
-
@source = src
|
76
|
-
src.configure(self)
|
77
|
-
end
|
78
|
-
|
79
|
-
def check_for_smells
|
80
|
-
return if @already_checked_for_smells
|
81
|
-
CodeParser.new(self).process(@source.syntax_tree)
|
82
|
-
@already_checked_for_smells = true
|
83
|
-
end
|
84
|
-
|
85
|
-
def configure(klass, config)
|
86
|
-
@detectors[klass].push(config)
|
87
|
-
end
|
88
|
-
|
89
|
-
def report_on(report)
|
90
|
-
check_for_smells
|
91
|
-
@detectors.each_value { |stack| stack.report_on(report) }
|
92
|
-
end
|
93
|
-
|
94
|
-
def examine(scope, type)
|
95
|
-
listeners = smell_listeners[type]
|
96
|
-
listeners.each {|smell| smell.examine(scope) } if listeners
|
97
|
-
end
|
98
|
-
|
99
|
-
def smelly?
|
100
|
-
check_for_smells
|
101
|
-
@detectors.each_value { |stack| return true if stack.smelly? }
|
102
|
-
false
|
103
|
-
end
|
104
|
-
|
105
|
-
def num_smells
|
106
|
-
check_for_smells
|
107
|
-
total = 0
|
108
|
-
@detectors.each_value { |stack| total += stack.num_smells }
|
109
|
-
total
|
110
|
-
end
|
111
|
-
|
112
|
-
def desc
|
113
|
-
# SMELL: Special Case
|
114
|
-
# Only used in the Report tests, because they don't always create a Source.
|
115
|
-
@source ? @source.desc : "unknown"
|
116
|
-
end
|
117
|
-
|
118
|
-
#
|
119
|
-
# Checks for instances of +smell_class+, and returns +true+
|
120
|
-
# only if one of them has a report string matching all of the +patterns+.
|
121
|
-
#
|
122
|
-
def has_smell?(smell_class, patterns=[])
|
123
|
-
check_for_smells
|
124
|
-
stack = @detectors[Reek::Smells.const_get(smell_class)] # SMELL: Duplication of code in ConfigFile
|
125
|
-
stack.has_smell?(patterns)
|
126
|
-
end
|
127
|
-
|
128
|
-
def sniff
|
129
|
-
self
|
130
|
-
end
|
131
|
-
|
132
|
-
def sniffers
|
133
|
-
[self]
|
134
|
-
end
|
135
|
-
|
136
|
-
private
|
137
|
-
|
138
|
-
def smell_listeners()
|
139
|
-
unless @typed_detectors
|
140
|
-
@typed_detectors = Hash.new {|hash,key| hash[key] = [] }
|
141
|
-
@detectors.each_value { |stack| stack.listen_to(@typed_detectors) }
|
142
|
-
end
|
143
|
-
@typed_detectors
|
144
|
-
end
|
145
|
-
end
|
146
|
-
|
147
|
-
class SnifferSet
|
148
|
-
|
149
|
-
attr_reader :desc, :sniffers
|
150
|
-
|
151
|
-
def initialize(sniffers, desc)
|
152
|
-
@sniffers = sniffers
|
153
|
-
@desc = desc
|
154
|
-
end
|
155
|
-
|
156
|
-
def smelly?
|
157
|
-
@sniffers.any? {|sniffer| sniffer.smelly? }
|
158
|
-
end
|
159
|
-
|
160
|
-
#
|
161
|
-
# Checks for instances of +smell_class+, and returns +true+
|
162
|
-
# only if one of them has a report string matching all of the +patterns+.
|
163
|
-
#
|
164
|
-
def has_smell?(smell_class, patterns=[])
|
165
|
-
@sniffers.any? {|sniffer| sniffer.has_smell?(smell_class, patterns)}
|
166
|
-
end
|
167
|
-
|
168
|
-
def num_smells
|
169
|
-
@sniffers.inject(0) {|total, sniffer| total += sniffer.num_smells}
|
170
|
-
end
|
171
|
-
|
172
|
-
def sniff
|
173
|
-
self
|
174
|
-
end
|
175
|
-
|
176
|
-
end
|
177
|
-
end
|