kevinrutherford-reek 1.1.3.14 → 1.1.3.15
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +2 -0
- data/config/defaults.reek +6 -0
- data/features/samples.feature +4 -2
- data/lib/reek/class_context.rb +7 -3
- data/lib/reek/code_parser.rb +1 -8
- data/lib/reek/method_context.rb +53 -11
- data/lib/reek/name.rb +8 -2
- data/lib/reek/smells/data_clump.rb +88 -0
- data/lib/reek/sniffer.rb +19 -16
- data/lib/reek.rb +1 -1
- data/reek.gemspec +3 -3
- data/spec/reek/block_context_spec.rb +1 -1
- data/spec/reek/name_spec.rb +24 -0
- data/spec/reek/singleton_method_context_spec.rb +1 -1
- data/spec/reek/smells/data_clump_spec.rb +87 -0
- data/spec/reek/smells/large_class_spec.rb +1 -1
- data/spec/reek/smells/uncommunicative_name_spec.rb +2 -2
- metadata +5 -4
data/History.txt
CHANGED
@@ -2,6 +2,8 @@
|
|
2
2
|
|
3
3
|
=== Major Changes
|
4
4
|
* Reek passes all its tests under ruby 1.8.6, 1.8.7 and 1.9.1 (fixed #16)
|
5
|
+
* New smell -- Data Clump:
|
6
|
+
** Looks within a class for 3 or more methods taking the same 2 or more parameters
|
5
7
|
* New smell -- Simulated Polymorphism:
|
6
8
|
** Currently only performs basic check for multiple tests of same value
|
7
9
|
* Reek's output reports are now formatted differently:
|
data/config/defaults.reek
CHANGED
data/features/samples.feature
CHANGED
@@ -9,8 +9,9 @@ Feature: Basic smell detection
|
|
9
9
|
Then it fails with exit status 2
|
10
10
|
And it reports:
|
11
11
|
"""
|
12
|
-
spec/samples/inline.rb --
|
12
|
+
spec/samples/inline.rb -- 36 warnings (+1 masked):
|
13
13
|
Inline::C has at least 13 instance variables (Large Class)
|
14
|
+
Inline::C takes parameters [options, src] to 5 methods (Data Clump)
|
14
15
|
Inline::C tests $DEBUG at least 7 times (Simulated Polymorphism)
|
15
16
|
Inline::C tests $TESTING at least 4 times (Simulated Polymorphism)
|
16
17
|
Inline::C tests @@type_map.has_key?(type) at least 3 times (Simulated Polymorphism)
|
@@ -183,8 +184,9 @@ Feature: Basic smell detection
|
|
183
184
|
Then it fails with exit status 2
|
184
185
|
And it reports:
|
185
186
|
"""
|
186
|
-
spec/samples/redcloth.rb --
|
187
|
+
spec/samples/redcloth.rb -- 100 warnings:
|
187
188
|
RedCloth has at least 44 methods (Large Class)
|
189
|
+
RedCloth takes parameters [atts, cite, content, tag] to 3 methods (Data Clump)
|
188
190
|
RedCloth tests atts at least 6 times (Simulated Polymorphism)
|
189
191
|
RedCloth tests codepre.zero? at least 3 times (Simulated Polymorphism)
|
190
192
|
RedCloth tests href at least 3 times (Simulated Polymorphism)
|
data/lib/reek/class_context.rb
CHANGED
@@ -24,7 +24,7 @@ module Reek
|
|
24
24
|
CodeParser.new(sniffer).process_class(source.syntax_tree)
|
25
25
|
end
|
26
26
|
|
27
|
-
attr_reader :conditionals
|
27
|
+
attr_reader :conditionals, :parsed_methods
|
28
28
|
|
29
29
|
# SMELL: inconsistent with other contexts (not linked to the sexp)
|
30
30
|
def initialize(outer, name, superclass = nil)
|
@@ -62,8 +62,8 @@ module Reek
|
|
62
62
|
@instance_variables << Name.new(sym)
|
63
63
|
end
|
64
64
|
|
65
|
-
def record_method(
|
66
|
-
@parsed_methods <<
|
65
|
+
def record_method(meth)
|
66
|
+
@parsed_methods << meth
|
67
67
|
end
|
68
68
|
|
69
69
|
def outer_name
|
@@ -81,5 +81,9 @@ module Reek
|
|
81
81
|
def record_conditional(exp)
|
82
82
|
@conditionals << exp
|
83
83
|
end
|
84
|
+
|
85
|
+
def parameterized_methods(min_clump_size)
|
86
|
+
parsed_methods.select {|meth| meth.parameters.length >= min_clump_size }
|
87
|
+
end
|
84
88
|
end
|
85
89
|
end
|
data/lib/reek/code_parser.rb
CHANGED
@@ -74,9 +74,7 @@ module Reek
|
|
74
74
|
handle_context(SingletonMethodContext, :defs, exp)
|
75
75
|
end
|
76
76
|
|
77
|
-
def process_args(exp)
|
78
|
-
exp[1..-1].each {|sym| @element.record_parameter(sym) }
|
79
|
-
end
|
77
|
+
def process_args(exp) end
|
80
78
|
|
81
79
|
def process_attrset(exp)
|
82
80
|
@element.record_depends_on_self if /^@/ === exp[1].to_s
|
@@ -95,11 +93,6 @@ module Reek
|
|
95
93
|
process(exp[1])
|
96
94
|
handle_context(BlockContext, :iter, exp[2..-1])
|
97
95
|
end
|
98
|
-
|
99
|
-
def process_dasgn_curr(exp)
|
100
|
-
@element.record_parameter(exp[1])
|
101
|
-
process_default(exp)
|
102
|
-
end
|
103
96
|
|
104
97
|
def process_block(exp)
|
105
98
|
@element.count_statements(CodeParser.count_statements(exp))
|
data/lib/reek/method_context.rb
CHANGED
@@ -2,7 +2,55 @@ require 'reek/name'
|
|
2
2
|
require 'reek/code_context'
|
3
3
|
require 'reek/object_refs'
|
4
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
|
+
|
5
28
|
module Reek
|
29
|
+
|
30
|
+
module MethodParameters
|
31
|
+
def self.is_arg?(param)
|
32
|
+
return false if (Array === param and param[0] == :block)
|
33
|
+
return !(param.to_s =~ /^\&/)
|
34
|
+
end
|
35
|
+
|
36
|
+
def names
|
37
|
+
return @names if @names
|
38
|
+
@names = self[1..-1].select {|arg| MethodParameters.is_arg?(arg)}.map {|arg| Name.new(arg)}
|
39
|
+
end
|
40
|
+
|
41
|
+
def length
|
42
|
+
names.length
|
43
|
+
end
|
44
|
+
|
45
|
+
def include?(name)
|
46
|
+
names.include?(name)
|
47
|
+
end
|
48
|
+
|
49
|
+
def to_s
|
50
|
+
"[#{names.map{|nm| nm.to_s}.join(', ')}]"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
6
54
|
class MethodContext < CodeContext
|
7
55
|
attr_reader :parameters
|
8
56
|
attr_reader :calls
|
@@ -11,14 +59,16 @@ module Reek
|
|
11
59
|
|
12
60
|
def initialize(outer, exp, record = true)
|
13
61
|
super(outer, exp)
|
14
|
-
@parameters = []
|
62
|
+
@parameters = exp[exp[0] == :defn ? 2 : 3] # SMELL: SimulatedPolymorphism
|
63
|
+
@parameters ||= []
|
64
|
+
@parameters.extend(MethodParameters)
|
15
65
|
@local_variables = []
|
16
66
|
@name = Name.new(exp[1])
|
17
67
|
@num_statements = 0
|
18
68
|
@calls = Hash.new(0)
|
19
69
|
@depends_on_self = false
|
20
70
|
@refs = ObjectRefs.new
|
21
|
-
@outer.record_method(
|
71
|
+
@outer.record_method(self)
|
22
72
|
end
|
23
73
|
|
24
74
|
def count_statements(num)
|
@@ -63,14 +113,6 @@ module Reek
|
|
63
113
|
@local_variables << Name.new(sym)
|
64
114
|
end
|
65
115
|
|
66
|
-
def self.is_block_arg?(param)
|
67
|
-
(Array === param and param[0] == :block) or (param.to_s =~ /^\&/)
|
68
|
-
end
|
69
|
-
|
70
|
-
def record_parameter(param)
|
71
|
-
@parameters << Name.new(param) unless MethodContext.is_block_arg?(param)
|
72
|
-
end
|
73
|
-
|
74
116
|
def outer_name
|
75
117
|
"#{@outer.outer_name}#{@name}/"
|
76
118
|
end
|
@@ -85,7 +127,7 @@ module Reek
|
|
85
127
|
end
|
86
128
|
|
87
129
|
def variable_names
|
88
|
-
@parameters + @local_variables
|
130
|
+
@parameters.names + @local_variables
|
89
131
|
end
|
90
132
|
end
|
91
133
|
end
|
data/lib/reek/name.rb
CHANGED
@@ -32,16 +32,22 @@ module Reek
|
|
32
32
|
@name.hash
|
33
33
|
end
|
34
34
|
|
35
|
+
def eql?(other)
|
36
|
+
self == other
|
37
|
+
end
|
38
|
+
|
35
39
|
def <=>(other) # :nodoc:
|
36
40
|
@name <=> other.to_s
|
37
41
|
end
|
38
42
|
|
39
|
-
alias eql? <=>
|
40
|
-
|
41
43
|
def effective_name
|
42
44
|
@name.gsub(/^@*/, '')
|
43
45
|
end
|
44
46
|
|
47
|
+
def inspect
|
48
|
+
@name.inspect
|
49
|
+
end
|
50
|
+
|
45
51
|
def to_s
|
46
52
|
@name
|
47
53
|
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'reek/smells/smell_detector'
|
2
|
+
require 'reek/smell_warning'
|
3
|
+
require 'reek/sexp_formatter'
|
4
|
+
|
5
|
+
module Reek
|
6
|
+
module Smells
|
7
|
+
|
8
|
+
#
|
9
|
+
# A Data Clump occurs when the same two or three items frequently
|
10
|
+
# appear together in classes and parameter lists, or when a group
|
11
|
+
# of instance variable names start or end with similar substrings.
|
12
|
+
#
|
13
|
+
# The recurrence of the items often means there is duplicate code
|
14
|
+
# spread around to handle them. There may be an abstraction missing
|
15
|
+
# from the code, making the system harder to understand.
|
16
|
+
#
|
17
|
+
# Currently Reek looks for a group of two or more parameters with
|
18
|
+
# the same names that are expected by three or more methods of a class.
|
19
|
+
#
|
20
|
+
class DataClump < SmellDetector
|
21
|
+
|
22
|
+
def self.contexts # :nodoc:
|
23
|
+
[:class]
|
24
|
+
end
|
25
|
+
|
26
|
+
# The name of the config field that sets the maximum allowed
|
27
|
+
# copies of any clump.
|
28
|
+
MAX_COPIES_KEY = 'max_copies'
|
29
|
+
|
30
|
+
DEFAULT_MAX_COPIES = 2
|
31
|
+
|
32
|
+
MIN_CLUMP_SIZE_KEY = 'min_clump_size'
|
33
|
+
DEFAULT_MIN_CLUMP_SIZE = 2
|
34
|
+
|
35
|
+
def self.default_config
|
36
|
+
super.adopt(
|
37
|
+
MAX_COPIES_KEY => DEFAULT_MAX_COPIES,
|
38
|
+
MIN_CLUMP_SIZE_KEY => DEFAULT_MIN_CLUMP_SIZE
|
39
|
+
)
|
40
|
+
end
|
41
|
+
|
42
|
+
def initialize(config = DataClump.default_config)
|
43
|
+
super(config)
|
44
|
+
end
|
45
|
+
|
46
|
+
#
|
47
|
+
# Checks the given ClassContext for multiple identical conditional tests.
|
48
|
+
# Remembers any smells found.
|
49
|
+
#
|
50
|
+
def examine_context(klass)
|
51
|
+
max_copies = value(MAX_COPIES_KEY, klass, DEFAULT_MAX_COPIES)
|
52
|
+
min_clump_size = value(MIN_CLUMP_SIZE_KEY, klass, DEFAULT_MIN_CLUMP_SIZE)
|
53
|
+
MethodGroup.new(klass, min_clump_size, max_copies).clumps.each do |clump, occurs|
|
54
|
+
found(klass, "takes parameters #{DataClump.print_clump(clump)} to #{occurs} methods")
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.print_clump(clump)
|
59
|
+
"[#{clump.map {|name| name.to_s}.join(', ')}]"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# Represents a group of methods
|
65
|
+
class MethodGroup # :nodoc:
|
66
|
+
|
67
|
+
def self.intersection_of_parameters_of(methods)
|
68
|
+
methods.map {|meth| meth.parameters.names.sort}.intersection
|
69
|
+
end
|
70
|
+
|
71
|
+
def initialize(klass, min_clump_size, max_copies)
|
72
|
+
@klass = klass
|
73
|
+
@min_clump_size = min_clump_size
|
74
|
+
@max_copies = max_copies
|
75
|
+
end
|
76
|
+
|
77
|
+
def clumps
|
78
|
+
results = Hash.new(0)
|
79
|
+
@klass.parameterized_methods(@min_clump_size).bounded_power_set(@max_copies).each do |methods|
|
80
|
+
clump = MethodGroup.intersection_of_parameters_of(methods)
|
81
|
+
if clump.length >= @min_clump_size
|
82
|
+
results[clump] = [methods.length, results[clump]].max
|
83
|
+
end
|
84
|
+
end
|
85
|
+
results
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
data/lib/reek/sniffer.rb
CHANGED
@@ -2,6 +2,7 @@ require 'reek/detector_stack'
|
|
2
2
|
|
3
3
|
# SMELL: Duplication -- all these should be found automagically
|
4
4
|
require 'reek/smells/control_couple'
|
5
|
+
require 'reek/smells/data_clump'
|
5
6
|
require 'reek/smells/duplication'
|
6
7
|
require 'reek/smells/feature_envy'
|
7
8
|
require 'reek/smells/large_class'
|
@@ -44,27 +45,29 @@ end
|
|
44
45
|
module Reek
|
45
46
|
class Sniffer
|
46
47
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
48
|
+
def self.smell_classes
|
49
|
+
# SMELL: Duplication -- these should be loaded by listing the files
|
50
|
+
[
|
51
|
+
Smells::ControlCouple,
|
52
|
+
Smells::DataClump,
|
53
|
+
Smells::Duplication,
|
54
|
+
Smells::FeatureEnvy,
|
55
|
+
Smells::LargeClass,
|
56
|
+
Smells::LongMethod,
|
57
|
+
Smells::LongParameterList,
|
58
|
+
Smells::LongYieldList,
|
59
|
+
Smells::NestedIterators,
|
60
|
+
Smells::SimulatedPolymorphism,
|
61
|
+
Smells::UncommunicativeName,
|
62
|
+
Smells::UtilityFunction,
|
63
|
+
]
|
64
|
+
end
|
62
65
|
|
63
66
|
def initialize(src)
|
64
67
|
@already_checked_for_smells = false
|
65
68
|
@typed_detectors = nil
|
66
69
|
@detectors = Hash.new
|
67
|
-
|
70
|
+
Sniffer.smell_classes.each { |klass| @detectors[klass] = DetectorStack.new(klass.new) }
|
68
71
|
@source = src
|
69
72
|
src.configure(self)
|
70
73
|
end
|
data/lib/reek.rb
CHANGED
data/reek.gemspec
CHANGED
@@ -2,17 +2,17 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{reek}
|
5
|
-
s.version = "1.1.3.
|
5
|
+
s.version = "1.1.3.15"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Kevin Rutherford"]
|
9
|
-
s.date = %q{2009-
|
9
|
+
s.date = %q{2009-09-03}
|
10
10
|
s.default_executable = %q{reek}
|
11
11
|
s.description = %q{Code smell detector for Ruby}
|
12
12
|
s.email = ["kevin@rutherford-software.com"]
|
13
13
|
s.executables = ["reek"]
|
14
14
|
s.extra_rdoc_files = ["History.txt", "License.txt", "README.txt"]
|
15
|
-
s.files = ["History.txt", "License.txt", "README.txt", "Rakefile", "bin/reek", "config/defaults.reek", "features/masking_smells.feature", "features/options.feature", "features/reports.feature", "features/samples.feature", "features/stdin.feature", "features/step_definitions/reek_steps.rb", "features/support/env.rb", "lib/reek.rb", "lib/reek/adapters/application.rb", "lib/reek/adapters/config_file.rb", "lib/reek/adapters/core_extras.rb", "lib/reek/adapters/object_source.rb", "lib/reek/adapters/rake_task.rb", "lib/reek/adapters/report.rb", "lib/reek/adapters/source.rb", "lib/reek/adapters/spec.rb", "lib/reek/block_context.rb", "lib/reek/class_context.rb", "lib/reek/code_context.rb", "lib/reek/code_parser.rb", "lib/reek/command_line.rb", "lib/reek/configuration.rb", "lib/reek/detector_stack.rb", "lib/reek/exceptions.reek", "lib/reek/if_context.rb", "lib/reek/method_context.rb", "lib/reek/module_context.rb", "lib/reek/name.rb", "lib/reek/object_refs.rb", "lib/reek/sexp_formatter.rb", "lib/reek/singleton_method_context.rb", "lib/reek/smell_warning.rb", "lib/reek/smells/control_couple.rb", "lib/reek/smells/duplication.rb", "lib/reek/smells/feature_envy.rb", "lib/reek/smells/large_class.rb", "lib/reek/smells/long_method.rb", "lib/reek/smells/long_parameter_list.rb", "lib/reek/smells/long_yield_list.rb", "lib/reek/smells/nested_iterators.rb", "lib/reek/smells/simulated_polymorphism.rb", "lib/reek/smells/smell_detector.rb", "lib/reek/smells/uncommunicative_name.rb", "lib/reek/smells/utility_function.rb", "lib/reek/sniffer.rb", "lib/reek/stop_context.rb", "lib/reek/yield_call_context.rb", "reek.gemspec", "spec/quality/reek_source_spec.rb", "spec/reek/adapters/report_spec.rb", "spec/reek/adapters/should_reek_of_spec.rb", "spec/reek/adapters/should_reek_only_of_spec.rb", "spec/reek/adapters/should_reek_spec.rb", "spec/reek/block_context_spec.rb", "spec/reek/class_context_spec.rb", "spec/reek/code_context_spec.rb", "spec/reek/code_parser_spec.rb", "spec/reek/config_spec.rb", "spec/reek/configuration_spec.rb", "spec/reek/if_context_spec.rb", "spec/reek/method_context_spec.rb", "spec/reek/module_context_spec.rb", "spec/reek/name_spec.rb", "spec/reek/object_refs_spec.rb", "spec/reek/object_source_spec.rb", "spec/reek/singleton_method_context_spec.rb", "spec/reek/smell_warning_spec.rb", "spec/reek/smells/control_couple_spec.rb", "spec/reek/smells/duplication_spec.rb", "spec/reek/smells/feature_envy_spec.rb", "spec/reek/smells/large_class_spec.rb", "spec/reek/smells/long_method_spec.rb", "spec/reek/smells/long_parameter_list_spec.rb", "spec/reek/smells/nested_iterators_spec.rb", "spec/reek/smells/simulated_polymorphism_spec.rb", "spec/reek/smells/smell_detector_spec.rb", "spec/reek/smells/uncommunicative_name_spec.rb", "spec/reek/smells/utility_function_spec.rb", "spec/reek/sniffer_spec.rb", "spec/samples/all_but_one_masked/clean_one.rb", "spec/samples/all_but_one_masked/dirty.rb", "spec/samples/all_but_one_masked/masked.reek", "spec/samples/clean_due_to_masking/clean_one.rb", "spec/samples/clean_due_to_masking/clean_three.rb", "spec/samples/clean_due_to_masking/clean_two.rb", "spec/samples/clean_due_to_masking/dirty_one.rb", "spec/samples/clean_due_to_masking/dirty_two.rb", "spec/samples/clean_due_to_masking/masked.reek", "spec/samples/corrupt_config_file/corrupt.reek", "spec/samples/corrupt_config_file/dirty.rb", "spec/samples/empty_config_file/dirty.rb", "spec/samples/empty_config_file/empty.reek", "spec/samples/exceptions.reek", "spec/samples/inline.rb", "spec/samples/masked/dirty.rb", "spec/samples/masked/masked.reek", "spec/samples/mixed_results/clean_one.rb", "spec/samples/mixed_results/clean_three.rb", "spec/samples/mixed_results/clean_two.rb", "spec/samples/mixed_results/dirty_one.rb", "spec/samples/mixed_results/dirty_two.rb", "spec/samples/not_quite_masked/dirty.rb", "spec/samples/not_quite_masked/masked.reek", "spec/samples/optparse.rb", "spec/samples/overrides/masked/dirty.rb", "spec/samples/overrides/masked/lower.reek", "spec/samples/overrides/upper.reek", "spec/samples/redcloth.rb", "spec/samples/three_clean_files/clean_one.rb", "spec/samples/three_clean_files/clean_three.rb", "spec/samples/three_clean_files/clean_two.rb", "spec/samples/two_smelly_files/dirty_one.rb", "spec/samples/two_smelly_files/dirty_two.rb", "spec/spec.opts", "spec/spec_helper.rb", "tasks/reek.rake", "tasks/test.rake"]
|
15
|
+
s.files = ["History.txt", "License.txt", "README.txt", "Rakefile", "bin/reek", "config/defaults.reek", "features/masking_smells.feature", "features/options.feature", "features/reports.feature", "features/samples.feature", "features/stdin.feature", "features/step_definitions/reek_steps.rb", "features/support/env.rb", "lib/reek.rb", "lib/reek/adapters/application.rb", "lib/reek/adapters/config_file.rb", "lib/reek/adapters/core_extras.rb", "lib/reek/adapters/object_source.rb", "lib/reek/adapters/rake_task.rb", "lib/reek/adapters/report.rb", "lib/reek/adapters/source.rb", "lib/reek/adapters/spec.rb", "lib/reek/block_context.rb", "lib/reek/class_context.rb", "lib/reek/code_context.rb", "lib/reek/code_parser.rb", "lib/reek/command_line.rb", "lib/reek/configuration.rb", "lib/reek/detector_stack.rb", "lib/reek/exceptions.reek", "lib/reek/if_context.rb", "lib/reek/method_context.rb", "lib/reek/module_context.rb", "lib/reek/name.rb", "lib/reek/object_refs.rb", "lib/reek/sexp_formatter.rb", "lib/reek/singleton_method_context.rb", "lib/reek/smell_warning.rb", "lib/reek/smells/control_couple.rb", "lib/reek/smells/data_clump.rb", "lib/reek/smells/duplication.rb", "lib/reek/smells/feature_envy.rb", "lib/reek/smells/large_class.rb", "lib/reek/smells/long_method.rb", "lib/reek/smells/long_parameter_list.rb", "lib/reek/smells/long_yield_list.rb", "lib/reek/smells/nested_iterators.rb", "lib/reek/smells/simulated_polymorphism.rb", "lib/reek/smells/smell_detector.rb", "lib/reek/smells/uncommunicative_name.rb", "lib/reek/smells/utility_function.rb", "lib/reek/sniffer.rb", "lib/reek/stop_context.rb", "lib/reek/yield_call_context.rb", "reek.gemspec", "spec/quality/reek_source_spec.rb", "spec/reek/adapters/report_spec.rb", "spec/reek/adapters/should_reek_of_spec.rb", "spec/reek/adapters/should_reek_only_of_spec.rb", "spec/reek/adapters/should_reek_spec.rb", "spec/reek/block_context_spec.rb", "spec/reek/class_context_spec.rb", "spec/reek/code_context_spec.rb", "spec/reek/code_parser_spec.rb", "spec/reek/config_spec.rb", "spec/reek/configuration_spec.rb", "spec/reek/if_context_spec.rb", "spec/reek/method_context_spec.rb", "spec/reek/module_context_spec.rb", "spec/reek/name_spec.rb", "spec/reek/object_refs_spec.rb", "spec/reek/object_source_spec.rb", "spec/reek/singleton_method_context_spec.rb", "spec/reek/smell_warning_spec.rb", "spec/reek/smells/control_couple_spec.rb", "spec/reek/smells/data_clump_spec.rb", "spec/reek/smells/duplication_spec.rb", "spec/reek/smells/feature_envy_spec.rb", "spec/reek/smells/large_class_spec.rb", "spec/reek/smells/long_method_spec.rb", "spec/reek/smells/long_parameter_list_spec.rb", "spec/reek/smells/nested_iterators_spec.rb", "spec/reek/smells/simulated_polymorphism_spec.rb", "spec/reek/smells/smell_detector_spec.rb", "spec/reek/smells/uncommunicative_name_spec.rb", "spec/reek/smells/utility_function_spec.rb", "spec/reek/sniffer_spec.rb", "spec/samples/all_but_one_masked/clean_one.rb", "spec/samples/all_but_one_masked/dirty.rb", "spec/samples/all_but_one_masked/masked.reek", "spec/samples/clean_due_to_masking/clean_one.rb", "spec/samples/clean_due_to_masking/clean_three.rb", "spec/samples/clean_due_to_masking/clean_two.rb", "spec/samples/clean_due_to_masking/dirty_one.rb", "spec/samples/clean_due_to_masking/dirty_two.rb", "spec/samples/clean_due_to_masking/masked.reek", "spec/samples/corrupt_config_file/corrupt.reek", "spec/samples/corrupt_config_file/dirty.rb", "spec/samples/empty_config_file/dirty.rb", "spec/samples/empty_config_file/empty.reek", "spec/samples/exceptions.reek", "spec/samples/inline.rb", "spec/samples/masked/dirty.rb", "spec/samples/masked/masked.reek", "spec/samples/mixed_results/clean_one.rb", "spec/samples/mixed_results/clean_three.rb", "spec/samples/mixed_results/clean_two.rb", "spec/samples/mixed_results/dirty_one.rb", "spec/samples/mixed_results/dirty_two.rb", "spec/samples/not_quite_masked/dirty.rb", "spec/samples/not_quite_masked/masked.reek", "spec/samples/optparse.rb", "spec/samples/overrides/masked/dirty.rb", "spec/samples/overrides/masked/lower.reek", "spec/samples/overrides/upper.reek", "spec/samples/redcloth.rb", "spec/samples/three_clean_files/clean_one.rb", "spec/samples/three_clean_files/clean_three.rb", "spec/samples/three_clean_files/clean_two.rb", "spec/samples/two_smelly_files/dirty_one.rb", "spec/samples/two_smelly_files/dirty_two.rb", "spec/spec.opts", "spec/spec_helper.rb", "tasks/reek.rake", "tasks/test.rake"]
|
16
16
|
s.homepage = %q{http://wiki.github.com/kevinrutherford/reek}
|
17
17
|
s.post_install_message = %q{
|
18
18
|
For more information on reek, see http://wiki.github.com/kevinrutherford/reek
|
@@ -27,7 +27,7 @@ describe BlockContext do
|
|
27
27
|
end
|
28
28
|
|
29
29
|
it "should not pass parameters upward" do
|
30
|
-
mc = MethodContext.new(StopContext.new, s(:defn, :help))
|
30
|
+
mc = MethodContext.new(StopContext.new, s(:defn, :help, s(:args)))
|
31
31
|
element = BlockContext.new(mc, s(s(:lasgn, :x)))
|
32
32
|
mc.variable_names.should be_empty
|
33
33
|
end
|
data/spec/reek/name_spec.rb
CHANGED
@@ -11,3 +11,27 @@ describe Name, 'resolving symbols' do
|
|
11
11
|
res[1].should == "LargeClass"
|
12
12
|
end
|
13
13
|
end
|
14
|
+
|
15
|
+
describe Name do
|
16
|
+
it 'compares correctly' do
|
17
|
+
a1 = [Name.new('conts'), Name.new('p1'), Name.new('p2'), Name.new('p3')]
|
18
|
+
a2 = [Name.new('name'), Name.new('windowH'), Name.new('windowW')]
|
19
|
+
(a1 & a2).should == []
|
20
|
+
end
|
21
|
+
|
22
|
+
it do
|
23
|
+
[Name.new(:fred)].should include(Name.new(:fred))
|
24
|
+
end
|
25
|
+
|
26
|
+
it do
|
27
|
+
set = Set.new
|
28
|
+
set << Name.new(:fred)
|
29
|
+
set.should include(Name.new(:fred))
|
30
|
+
end
|
31
|
+
|
32
|
+
it do
|
33
|
+
fred = Name.new(:fred)
|
34
|
+
fred.should eql(fred)
|
35
|
+
fred.should eql(Name.new(:fred))
|
36
|
+
end
|
37
|
+
end
|
@@ -11,7 +11,7 @@ describe SingletonMethodContext, 'outer_name' do
|
|
11
11
|
it "should report full context" do
|
12
12
|
element = StopContext.new
|
13
13
|
element = ModuleContext.new(element, Name.new(:mod))
|
14
|
-
element = SingletonMethodContext.new(element,
|
14
|
+
element = SingletonMethodContext.new(element, s(:defs, s(:call, nil, :a, s(:arglist)), :b, s(:args)))
|
15
15
|
element.outer_name.should match(/mod::a\.b/)
|
16
16
|
end
|
17
17
|
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper.rb'
|
2
|
+
|
3
|
+
require 'reek/smells/data_clump'
|
4
|
+
|
5
|
+
include Reek::Smells
|
6
|
+
|
7
|
+
describe DataClump do
|
8
|
+
it 'should not report small parameter sets' do
|
9
|
+
src = <<EOS
|
10
|
+
class Scrunch
|
11
|
+
def first(pa) @field == :sym ? 0 : 3; end
|
12
|
+
def second(pa) @field == :sym; end
|
13
|
+
def third(pa) pa - pb + @fred; end
|
14
|
+
end
|
15
|
+
EOS
|
16
|
+
|
17
|
+
src.should_not reek
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'should report 3 identical pairs in a class' do
|
21
|
+
src = <<EOS
|
22
|
+
class Scrunch
|
23
|
+
def first(pa, pb) @field == :sym ? 0 : 3; end
|
24
|
+
def second(pa, pb) @field == :sym; end
|
25
|
+
def third(pa, pb) pa - pb + @fred; end
|
26
|
+
end
|
27
|
+
EOS
|
28
|
+
|
29
|
+
src.should reek_of(:DataClump, /\[pa, pb\]/, /3 methods/)
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'should report 3 swapped pairs in a class' do
|
33
|
+
src = <<EOS
|
34
|
+
class Scrunch
|
35
|
+
def one(pa, pb) @field == :sym ? 0 : 3; end
|
36
|
+
def two(pb, pa) @field == :sym; end
|
37
|
+
def tri(pa, pb) pa - pb + @fred; end
|
38
|
+
end
|
39
|
+
EOS
|
40
|
+
|
41
|
+
src.should reek_of(:DataClump, /\[pa, pb\]/, /3 methods/)
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'should report 3 identical parameter sets in a class' do
|
45
|
+
src = <<EOS
|
46
|
+
class Scrunch
|
47
|
+
def first(pa, pb, pc) @field == :sym ? 0 : 3; end
|
48
|
+
def second(pa, pb, pc) @field == :sym; end
|
49
|
+
def third(pa, pb, pc) pa - pb + @fred; end
|
50
|
+
end
|
51
|
+
EOS
|
52
|
+
|
53
|
+
src.should reek_of(:DataClump, /\[pa, pb, pc\]/, /3 methods/)
|
54
|
+
src.should_not reek_of(:DataClump, /\[pa, pb\]/, /3 methods/)
|
55
|
+
src.should_not reek_of(:DataClump, /\[pa, pc\]/, /3 methods/)
|
56
|
+
src.should_not reek_of(:DataClump, /\[pb, pc\]/, /3 methods/)
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'should recognise re-ordered identical parameter sets' do
|
60
|
+
src = <<EOS
|
61
|
+
class Scrunch
|
62
|
+
def first(pb, pa, pc) @field == :sym ? 0 : 3; end
|
63
|
+
def second(pc, pb, pa) @field == :sym; end
|
64
|
+
def third(pa, pb, pc) pa - pb + @fred; end
|
65
|
+
end
|
66
|
+
EOS
|
67
|
+
|
68
|
+
src.should reek_of(:DataClump, /\[pa, pb, pc\]/, /3 methods/)
|
69
|
+
src.should_not reek_of(:DataClump, /\[pa, pb\]/, /3 methods/)
|
70
|
+
src.should_not reek_of(:DataClump, /\[pa, pc\]/, /3 methods/)
|
71
|
+
src.should_not reek_of(:DataClump, /\[pb, pc\]/, /3 methods/)
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'should count only identical parameter sets' do
|
75
|
+
src = <<EOS
|
76
|
+
class RedCloth
|
77
|
+
def fa(p1, p2, p3, conten) end
|
78
|
+
def fb(p1, p2, p3, conten) end
|
79
|
+
def fc(name, windowW, windowH) end
|
80
|
+
end
|
81
|
+
EOS
|
82
|
+
|
83
|
+
src.should_not reek_of(:DataClump)
|
84
|
+
end
|
85
|
+
|
86
|
+
# TODO: include singleton methods in the calcs
|
87
|
+
end
|
@@ -39,7 +39,7 @@ describe LargeClass, 'checking Class objects' do
|
|
39
39
|
it 'should not report class with 10 ivars' do
|
40
40
|
pending('test requires ParseTree') unless ObjectSource.can_parse_objects?
|
41
41
|
class ManyIvars
|
42
|
-
def
|
42
|
+
def meth
|
43
43
|
@vara = @varb = @varc = @vard = @vare
|
44
44
|
@varf = @varg = @varh = @vari = @varj
|
45
45
|
end
|
@@ -125,12 +125,12 @@ describe UncommunicativeName, '#examine' do
|
|
125
125
|
end
|
126
126
|
|
127
127
|
it 'should return true when reporting a smell' do
|
128
|
-
mc = MethodContext.new(StopContext.new,
|
128
|
+
mc = MethodContext.new(StopContext.new, s(:defn, :x, s(:args)))
|
129
129
|
@uc.examine(mc).should == true
|
130
130
|
end
|
131
131
|
|
132
132
|
it 'should return false when not reporting a smell' do
|
133
|
-
mc = MethodContext.new(StopContext.new,
|
133
|
+
mc = MethodContext.new(StopContext.new, s(:defn, :not_bad, s(:args)))
|
134
134
|
@uc.examine(mc).should == false
|
135
135
|
end
|
136
136
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kevinrutherford-reek
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.3.
|
4
|
+
version: 1.1.3.15
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kevin Rutherford
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-09-03 00:00:00 -07:00
|
13
13
|
default_executable: reek
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -93,6 +93,7 @@ files:
|
|
93
93
|
- lib/reek/singleton_method_context.rb
|
94
94
|
- lib/reek/smell_warning.rb
|
95
95
|
- lib/reek/smells/control_couple.rb
|
96
|
+
- lib/reek/smells/data_clump.rb
|
96
97
|
- lib/reek/smells/duplication.rb
|
97
98
|
- lib/reek/smells/feature_envy.rb
|
98
99
|
- lib/reek/smells/large_class.rb
|
@@ -128,6 +129,7 @@ files:
|
|
128
129
|
- spec/reek/singleton_method_context_spec.rb
|
129
130
|
- spec/reek/smell_warning_spec.rb
|
130
131
|
- spec/reek/smells/control_couple_spec.rb
|
132
|
+
- spec/reek/smells/data_clump_spec.rb
|
131
133
|
- spec/reek/smells/duplication_spec.rb
|
132
134
|
- spec/reek/smells/feature_envy_spec.rb
|
133
135
|
- spec/reek/smells/large_class_spec.rb
|
@@ -179,7 +181,6 @@ files:
|
|
179
181
|
- tasks/test.rake
|
180
182
|
has_rdoc: false
|
181
183
|
homepage: http://wiki.github.com/kevinrutherford/reek
|
182
|
-
licenses:
|
183
184
|
post_install_message: |
|
184
185
|
|
185
186
|
For more information on reek, see http://wiki.github.com/kevinrutherford/reek
|
@@ -204,7 +205,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
204
205
|
requirements: []
|
205
206
|
|
206
207
|
rubyforge_project: reek
|
207
|
-
rubygems_version: 1.
|
208
|
+
rubygems_version: 1.2.0
|
208
209
|
signing_key:
|
209
210
|
specification_version: 3
|
210
211
|
summary: Code smell detector for Ruby
|