reek 1.2.6 → 1.2.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.yardopts +10 -0
- data/History.txt +62 -0
- data/README.md +74 -0
- data/bin/reek +2 -2
- data/config/defaults.reek +44 -5
- data/features/api.feature +20 -0
- data/features/masking_smells.feature +60 -42
- data/features/options.feature +7 -2
- data/features/rake_task.feature +29 -22
- data/features/reports.feature +9 -41
- data/features/samples.feature +184 -196
- data/features/stdin.feature +5 -8
- data/features/step_definitions/reek_steps.rb +8 -4
- data/features/support/env.rb +2 -3
- data/features/yaml.feature +85 -0
- data/lib/reek/cli/application.rb +46 -0
- data/lib/reek/cli/command_line.rb +108 -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 +58 -0
- data/lib/reek/cli/version_command.rb +19 -0
- data/lib/reek/cli/yaml_command.rb +32 -0
- data/lib/reek/core/code_context.rb +64 -0
- data/lib/reek/core/code_parser.rb +166 -0
- data/lib/reek/core/method_context.rb +84 -0
- data/lib/reek/core/module_context.rb +20 -0
- data/lib/reek/core/object_refs.rb +51 -0
- data/lib/reek/core/singleton_method_context.rb +20 -0
- data/lib/reek/core/smell_configuration.rb +62 -0
- data/lib/reek/core/sniffer.rb +105 -0
- data/lib/reek/core/stop_context.rb +30 -0
- data/lib/reek/core/warning_collector.rb +27 -0
- data/lib/reek/examiner.rb +104 -0
- data/lib/reek/rake/task.rb +142 -0
- data/lib/reek/smell_warning.rb +73 -23
- data/lib/reek/smells/attribute.rb +26 -21
- data/lib/reek/smells/boolean_parameter.rb +38 -0
- data/lib/reek/smells/class_variable.rb +22 -9
- data/lib/reek/smells/control_couple.rb +40 -16
- data/lib/reek/smells/data_clump.rb +114 -23
- data/lib/reek/smells/duplication.rb +55 -15
- data/lib/reek/smells/feature_envy.rb +16 -7
- data/lib/reek/smells/irresponsible_module.rb +37 -0
- data/lib/reek/smells/large_class.rb +37 -19
- data/lib/reek/smells/long_method.rb +20 -9
- data/lib/reek/smells/long_parameter_list.rb +22 -10
- data/lib/reek/smells/long_yield_list.rb +43 -7
- data/lib/reek/smells/nested_iterators.rb +68 -8
- data/lib/reek/smells/simulated_polymorphism.rb +26 -15
- data/lib/reek/smells/smell_detector.rb +29 -51
- data/lib/reek/smells/uncommunicative_method_name.rb +74 -0
- data/lib/reek/smells/uncommunicative_module_name.rb +74 -0
- data/lib/reek/smells/uncommunicative_parameter_name.rb +79 -0
- data/lib/reek/smells/uncommunicative_variable_name.rb +89 -0
- data/lib/reek/smells/utility_function.rb +51 -12
- data/lib/reek/smells.rb +29 -0
- data/lib/reek/source/code_comment.rb +37 -0
- data/lib/reek/source/config_file.rb +72 -0
- data/lib/reek/source/core_extras.rb +46 -0
- data/lib/reek/source/reference_collector.rb +28 -0
- data/lib/reek/source/sexp_formatter.rb +17 -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 +42 -0
- data/lib/reek/source/tree_dresser.rb +204 -0
- data/lib/reek/source.rb +18 -0
- data/lib/reek/spec/should_reek.rb +31 -0
- data/lib/reek/spec/should_reek_of.rb +37 -0
- data/lib/reek/spec/should_reek_only_of.rb +37 -0
- data/lib/reek/spec.rb +51 -0
- data/lib/reek.rb +8 -4
- data/reek.gemspec +9 -7
- data/spec/matchers/smell_of_matcher.rb +58 -0
- data/spec/reek/{help_command_spec.rb → cli/help_command_spec.rb} +3 -4
- data/spec/reek/cli/reek_command_spec.rb +46 -0
- data/spec/reek/cli/report_spec.rb +30 -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/code_context_spec.rb +145 -0
- data/spec/reek/{code_parser_spec.rb → core/code_parser_spec.rb} +7 -6
- data/spec/reek/{config_spec.rb → core/config_spec.rb} +2 -6
- data/spec/reek/{method_context_spec.rb → core/method_context_spec.rb} +16 -36
- data/spec/reek/core/module_context_spec.rb +27 -0
- data/spec/reek/{object_refs_spec.rb → core/object_refs_spec.rb} +5 -6
- data/spec/reek/core/singleton_method_context_spec.rb +9 -0
- data/spec/reek/core/smell_configuration_spec.rb +11 -0
- data/spec/reek/core/stop_context_spec.rb +17 -0
- data/spec/reek/core/warning_collector_spec.rb +27 -0
- data/spec/reek/examiner_spec.rb +103 -0
- data/spec/reek/smell_warning_spec.rb +74 -82
- data/spec/reek/smells/attribute_spec.rb +42 -23
- data/spec/reek/smells/behaves_like_variable_detector.rb +2 -2
- data/spec/reek/smells/boolean_parameter_spec.rb +66 -0
- data/spec/reek/smells/class_variable_spec.rb +60 -75
- data/spec/reek/smells/control_couple_spec.rb +37 -32
- data/spec/reek/smells/data_clump_spec.rb +63 -24
- data/spec/reek/smells/duplication_spec.rb +106 -57
- data/spec/reek/smells/feature_envy_spec.rb +113 -92
- data/spec/reek/smells/irresponsible_module_spec.rb +58 -0
- data/spec/reek/smells/large_class_spec.rb +67 -57
- data/spec/reek/smells/long_method_spec.rb +40 -10
- data/spec/reek/smells/long_parameter_list_spec.rb +50 -28
- data/spec/reek/smells/long_yield_list_spec.rb +57 -0
- data/spec/reek/smells/nested_iterators_spec.rb +115 -7
- data/spec/reek/smells/simulated_polymorphism_spec.rb +56 -20
- data/spec/reek/smells/smell_detector_shared.rb +42 -0
- data/spec/reek/smells/uncommunicative_method_name_spec.rb +42 -0
- data/spec/reek/smells/uncommunicative_module_name_spec.rb +66 -0
- data/spec/reek/smells/uncommunicative_parameter_name_spec.rb +71 -0
- data/spec/reek/smells/uncommunicative_variable_name_spec.rb +120 -0
- data/spec/reek/smells/utility_function_spec.rb +50 -4
- data/spec/reek/source/code_comment_spec.rb +82 -0
- data/spec/reek/source/object_source_spec.rb +20 -0
- data/spec/reek/source/reference_collector_spec.rb +53 -0
- data/spec/reek/{adapters/source_spec.rb → source/source_code_spec.rb} +7 -8
- data/spec/reek/source/tree_dresser_spec.rb +270 -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/config/allow_duplication.reek +3 -0
- data/spec/samples/config/deeper_nested_iterators.reek +3 -0
- data/spec/samples/corrupt_config_file/dirty.rb +1 -1
- data/spec/samples/demo/demo.rb +8 -0
- data/spec/samples/empty_config_file/dirty.rb +2 -1
- data/spec/samples/exceptions.reek +1 -1
- data/spec/samples/inline_config/dirty.rb +16 -0
- data/spec/samples/inline_config/masked.reek +7 -0
- data/spec/samples/mask_some/dirty.rb +8 -0
- data/spec/samples/mask_some/some.reek +8 -0
- 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 +10 -2
- data/tasks/reek.rake +2 -2
- data/tasks/test.rake +12 -3
- metadata +121 -79
- data/README.rdoc +0 -84
- data/features/profile.feature +0 -34
- 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/object_refs.rb +0 -49
- data/lib/reek/reek_command.rb +0 -28
- data/lib/reek/sexp_formatter.rb +0 -10
- data/lib/reek/singleton_method_context.rb +0 -26
- data/lib/reek/smells/uncommunicative_name.rb +0 -84
- 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/code_context_spec.rb +0 -182
- data/spec/reek/configuration_spec.rb +0 -12
- data/spec/reek/if_context_spec.rb +0 -17
- data/spec/reek/masking_collection_spec.rb +0 -236
- 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/reek_command_spec.rb +0 -45
- 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/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/object_refs.rb
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
module Reek
|
|
2
|
-
|
|
3
|
-
class ObjectRefs # :nodoc:
|
|
4
|
-
def initialize
|
|
5
|
-
@refs = Hash.new(0)
|
|
6
|
-
end
|
|
7
|
-
|
|
8
|
-
def record_reference_to_self
|
|
9
|
-
record_ref(SELF_REF)
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
def record_ref(exp)
|
|
13
|
-
type = exp[0]
|
|
14
|
-
case type
|
|
15
|
-
when :gvar
|
|
16
|
-
return
|
|
17
|
-
when :self
|
|
18
|
-
record_reference_to_self
|
|
19
|
-
else
|
|
20
|
-
@refs[exp] += 1
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
def refs_to_self
|
|
25
|
-
@refs[SELF_REF]
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
def max_refs
|
|
29
|
-
@refs.values.max or 0
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
# TODO
|
|
33
|
-
# Should be moved to Hash
|
|
34
|
-
#
|
|
35
|
-
def max_keys
|
|
36
|
-
max = max_refs
|
|
37
|
-
@refs.reject {|key,val| val != max}.keys
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
def self_is_max?
|
|
41
|
-
max_keys.length == 0 || @refs[SELF_REF] == max_refs
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
private
|
|
45
|
-
|
|
46
|
-
SELF_REF = Sexp.from_array([:lit, :self])
|
|
47
|
-
|
|
48
|
-
end
|
|
49
|
-
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
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
require 'reek/name'
|
|
2
|
-
require 'reek/method_context'
|
|
3
|
-
require 'reek/sexp_formatter'
|
|
4
|
-
|
|
5
|
-
module Reek
|
|
6
|
-
class SingletonMethodContext < MethodContext
|
|
7
|
-
|
|
8
|
-
def initialize(outer, exp)
|
|
9
|
-
super(outer, exp)
|
|
10
|
-
@name = Name.new(exp[2])
|
|
11
|
-
@receiver = SexpFormatter.format(exp[1])
|
|
12
|
-
@scope_connector = ""
|
|
13
|
-
record_depends_on_self
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
def envious_receivers
|
|
17
|
-
[]
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def full_name
|
|
21
|
-
outer = @outer ? @outer.full_name : ''
|
|
22
|
-
prefix = outer == '' ? '' : "#{outer}#"
|
|
23
|
-
"#{prefix}#{@receiver}.#{@name}"
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
end
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
require 'reek/smells/smell_detector'
|
|
2
|
-
require 'reek/smell_warning'
|
|
3
|
-
|
|
4
|
-
module Reek
|
|
5
|
-
module Smells
|
|
6
|
-
|
|
7
|
-
#
|
|
8
|
-
# An Uncommunicative Name is a name that doesn't communicate its intent
|
|
9
|
-
# well enough.
|
|
10
|
-
#
|
|
11
|
-
# Poor names make it hard for the reader to build a mental picture
|
|
12
|
-
# of what's going on in the code. They can also be mis-interpreted;
|
|
13
|
-
# and they hurt the flow of reading, because the reader must slow
|
|
14
|
-
# down to interpret the names.
|
|
15
|
-
#
|
|
16
|
-
# Currently +UncommunicativeName+ checks for
|
|
17
|
-
# * 1-character names
|
|
18
|
-
# * names ending with a number
|
|
19
|
-
#
|
|
20
|
-
class UncommunicativeName < SmellDetector
|
|
21
|
-
|
|
22
|
-
# The name of the config field that lists the regexps of
|
|
23
|
-
# smelly names to be reported.
|
|
24
|
-
REJECT_KEY = 'reject'
|
|
25
|
-
|
|
26
|
-
DEFAULT_REJECT_SET = [/^.$/, /[0-9]$/]
|
|
27
|
-
|
|
28
|
-
# The name of the config field that lists the specific names that are
|
|
29
|
-
# to be treated as exceptions; these names will not be reported as
|
|
30
|
-
# uncommunicative.
|
|
31
|
-
ACCEPT_KEY = 'accept'
|
|
32
|
-
|
|
33
|
-
DEFAULT_ACCEPT_SET = ['Inline::C']
|
|
34
|
-
|
|
35
|
-
def self.default_config
|
|
36
|
-
super.adopt(
|
|
37
|
-
REJECT_KEY => DEFAULT_REJECT_SET,
|
|
38
|
-
ACCEPT_KEY => DEFAULT_ACCEPT_SET
|
|
39
|
-
)
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
def self.contexts # :nodoc:
|
|
43
|
-
[:module, :class, :defn, :defs, :iter]
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
def initialize(config = UncommunicativeName.default_config)
|
|
47
|
-
super(config)
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
#
|
|
51
|
-
# Checks the given +context+ for uncommunicative names.
|
|
52
|
-
# Remembers any smells found.
|
|
53
|
-
#
|
|
54
|
-
def examine_context(context)
|
|
55
|
-
consider_name(context)
|
|
56
|
-
consider_variables(context)
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
def consider_variables(context) # :nodoc:
|
|
60
|
-
context.variable_names.each do |name|
|
|
61
|
-
next unless is_bad_name?(name, context)
|
|
62
|
-
found(context, "has the variable name '#{name}'")
|
|
63
|
-
end
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
def consider_name(context) # :nodoc:
|
|
67
|
-
name = context.name
|
|
68
|
-
return false if accept?(context)
|
|
69
|
-
return false unless is_bad_name?(name, context)
|
|
70
|
-
found(context, "has the name '#{name}'")
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
def accept?(context)
|
|
74
|
-
value(ACCEPT_KEY, context, DEFAULT_ACCEPT_SET).include?(context.full_name)
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
def is_bad_name?(name, context) # :nodoc:
|
|
78
|
-
var = name.effective_name
|
|
79
|
-
return false if var == '*' or value(ACCEPT_KEY, context, DEFAULT_ACCEPT_SET).include?(var)
|
|
80
|
-
value(REJECT_KEY, context, DEFAULT_REJECT_SET).detect {|patt| patt === var}
|
|
81
|
-
end
|
|
82
|
-
end
|
|
83
|
-
end
|
|
84
|
-
end
|
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
|
data/lib/reek/stop_context.rb
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
module Reek
|
|
2
|
-
class StopContext
|
|
3
|
-
|
|
4
|
-
def initialize
|
|
5
|
-
@refs = ObjectRefs.new
|
|
6
|
-
@name = ''
|
|
7
|
-
@myself = Object
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
def method_missing(method, *args)
|
|
11
|
-
nil
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def count_statements(num)
|
|
15
|
-
0
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def find_module(name)
|
|
19
|
-
sym = name.to_s
|
|
20
|
-
@myself.const_defined?(sym) ? @myself.const_get(sym) : nil
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def full_name
|
|
24
|
-
''
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
def inside_a_block?
|
|
28
|
-
false
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
def is_overriding_method?(name)
|
|
32
|
-
false
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
end
|