kevinrutherford-reek 1.1.3.13 → 1.1.3.14
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/History.txt +8 -2
- data/config/defaults.reek +13 -2
- data/features/masking_smells.feature +29 -1
- data/features/samples.feature +17 -4
- data/lib/reek/adapters/object_source.rb +2 -1
- data/lib/reek/class_context.rb +7 -0
- data/lib/reek/code_parser.rb +3 -1
- data/lib/reek/configuration.rb +51 -0
- data/lib/reek/detector_stack.rb +1 -3
- data/lib/reek/exceptions.reek +3 -0
- data/lib/reek/smell_warning.rb +10 -2
- data/lib/reek/smells/duplication.rb +4 -2
- data/lib/reek/smells/large_class.rb +8 -4
- data/lib/reek/smells/long_method.rb +4 -6
- data/lib/reek/smells/long_parameter_list.rb +11 -3
- data/lib/reek/smells/simulated_polymorphism.rb +58 -0
- data/lib/reek/smells/smell_detector.rb +53 -51
- data/lib/reek/smells/uncommunicative_name.rb +13 -9
- data/lib/reek/sniffer.rb +4 -0
- data/lib/reek.rb +1 -1
- data/reek.gemspec +3 -3
- data/spec/reek/adapters/report_spec.rb +5 -4
- data/spec/reek/class_context_spec.rb +21 -0
- data/spec/reek/configuration_spec.rb +12 -0
- data/spec/reek/smell_warning_spec.rb +30 -2
- data/spec/reek/smells/duplication_spec.rb +2 -1
- data/spec/reek/smells/feature_envy_spec.rb +15 -0
- data/spec/reek/smells/large_class_spec.rb +21 -20
- data/spec/reek/smells/simulated_polymorphism_spec.rb +50 -0
- data/spec/reek/smells/smell_detector_spec.rb +5 -5
- data/spec/reek/smells/uncommunicative_name_spec.rb +14 -0
- data/spec/samples/exceptions.reek +4 -0
- data/spec/samples/overrides/masked/dirty.rb +7 -0
- data/spec/samples/overrides/masked/lower.reek +5 -0
- data/spec/samples/overrides/upper.reek +5 -0
- data/tasks/test.rake +6 -1
- metadata +12 -3
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'reek/configuration'
|
2
|
+
|
1
3
|
class Class
|
2
4
|
def name_words
|
3
5
|
class_name = name.split(/::/)[-1]
|
@@ -15,37 +17,39 @@ module Reek
|
|
15
17
|
# smell that should ignore this code element.
|
16
18
|
EXCLUDE_KEY = 'exclude'
|
17
19
|
|
18
|
-
# The
|
19
|
-
#
|
20
|
-
|
21
|
-
|
22
|
-
def self.class_name
|
23
|
-
self.name.split(/::/)[-1]
|
24
|
-
end
|
20
|
+
# The default value for the +EXCLUDE_KEY+ if it isn't specified
|
21
|
+
# in any configuration file.
|
22
|
+
DEFAULT_EXCLUDE_SET = []
|
25
23
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
def self.default_config
|
31
|
-
{
|
32
|
-
ENABLED_KEY => true,
|
33
|
-
EXCLUDE_KEY => []
|
34
|
-
}
|
35
|
-
end
|
24
|
+
class << self
|
25
|
+
def class_name
|
26
|
+
self.name.split(/::/)[-1]
|
27
|
+
end
|
36
28
|
|
37
|
-
|
38
|
-
|
39
|
-
|
29
|
+
def contexts # :nodoc:
|
30
|
+
[:defn, :defs]
|
31
|
+
end
|
32
|
+
|
33
|
+
def default_config
|
34
|
+
{
|
35
|
+
SmellConfiguration::ENABLED_KEY => true,
|
36
|
+
EXCLUDE_KEY => DEFAULT_EXCLUDE_SET
|
37
|
+
}
|
38
|
+
end
|
40
39
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
40
|
+
def create(config)
|
41
|
+
new(config[class_name])
|
42
|
+
end
|
43
|
+
|
44
|
+
def listen(hooks, config)
|
45
|
+
detector = create(config)
|
46
|
+
detector.listen_to(hooks)
|
47
|
+
detector
|
48
|
+
end
|
45
49
|
end
|
46
50
|
|
47
51
|
def initialize(config = SmellDetector.default_config)
|
48
|
-
@config = config
|
52
|
+
@config = SmellConfiguration.new(config)
|
49
53
|
@smells_found = Set.new
|
50
54
|
@masked = false
|
51
55
|
end
|
@@ -54,16 +58,9 @@ module Reek
|
|
54
58
|
self.class.contexts.each { |ctx| hooks[ctx] << self }
|
55
59
|
end
|
56
60
|
|
57
|
-
|
58
|
-
@masked = true
|
59
|
-
end
|
60
|
-
|
61
|
-
def masked?
|
62
|
-
@masked
|
63
|
-
end
|
64
|
-
|
61
|
+
# SMELL: Getter (only used in 1 test)
|
65
62
|
def enabled?
|
66
|
-
@config
|
63
|
+
@config.enabled?
|
67
64
|
end
|
68
65
|
|
69
66
|
def configure(config)
|
@@ -73,16 +70,23 @@ module Reek
|
|
73
70
|
end
|
74
71
|
|
75
72
|
def configure_with(config)
|
76
|
-
@config.adopt!(config)
|
73
|
+
@config.hash.adopt!(config)
|
77
74
|
end
|
78
75
|
|
79
76
|
def copy
|
80
|
-
self.class.new(@config.deep_copy)
|
77
|
+
self.class.new(@config.hash.deep_copy)
|
78
|
+
end
|
79
|
+
|
80
|
+
def supersede_with(config)
|
81
|
+
clone = self.copy
|
82
|
+
@masked = true
|
83
|
+
clone.configure_with(config)
|
84
|
+
clone
|
81
85
|
end
|
82
86
|
|
83
87
|
def examine(context)
|
84
88
|
before = @smells_found.size
|
85
|
-
examine_context(context) if enabled? and !exception?(context)
|
89
|
+
examine_context(context) if @config.enabled? and !exception?(context)
|
86
90
|
@smells_found.length > before
|
87
91
|
end
|
88
92
|
|
@@ -90,29 +94,23 @@ module Reek
|
|
90
94
|
end
|
91
95
|
|
92
96
|
def exception?(context)
|
93
|
-
context.matches?(
|
97
|
+
context.matches?(value(EXCLUDE_KEY, context, DEFAULT_EXCLUDE_SET))
|
94
98
|
end
|
95
99
|
|
96
100
|
def found(scope, warning)
|
97
|
-
smell = SmellWarning.new(self, scope, warning)
|
101
|
+
smell = SmellWarning.new(self, scope, warning, @masked)
|
98
102
|
@smells_found << smell
|
99
103
|
smell
|
100
104
|
end
|
101
105
|
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
106
|
+
def has_smell?(patterns)
|
107
|
+
return false if @masked
|
108
|
+
@smells_found.each { |warning| return true if warning.contains_all?(patterns) }
|
109
|
+
false
|
110
|
+
end
|
107
111
|
|
108
112
|
def report_on(report)
|
109
|
-
@smells_found.each
|
110
|
-
if @masked
|
111
|
-
report.record_masked_smell(smell)
|
112
|
-
else
|
113
|
-
report << smell
|
114
|
-
end
|
115
|
-
end
|
113
|
+
@smells_found.each { |smell| smell.report_on(report) }
|
116
114
|
end
|
117
115
|
|
118
116
|
def num_smells
|
@@ -126,6 +124,10 @@ module Reek
|
|
126
124
|
def smell_name
|
127
125
|
self.class.name_words.join(' ')
|
128
126
|
end
|
127
|
+
|
128
|
+
def value(key, ctx, fall_back)
|
129
|
+
@config.value(key, ctx, fall_back)
|
130
|
+
end
|
129
131
|
end
|
130
132
|
end
|
131
133
|
end
|
@@ -15,23 +15,27 @@ module Reek
|
|
15
15
|
#
|
16
16
|
# Currently +UncommunicativeName+ checks for
|
17
17
|
# * 1-character names
|
18
|
-
# * names
|
18
|
+
# * names ending with a number
|
19
19
|
#
|
20
20
|
class UncommunicativeName < SmellDetector
|
21
21
|
|
22
22
|
# The name of the config field that lists the regexps of
|
23
23
|
# smelly names to be reported.
|
24
24
|
REJECT_KEY = 'reject'
|
25
|
+
|
26
|
+
DEFAULT_REJECT_SET = [/^.$/, /[0-9]$/]
|
25
27
|
|
26
28
|
# The name of the config field that lists the specific names that are
|
27
29
|
# to be treated as exceptions; these names will not be reported as
|
28
30
|
# uncommunicative.
|
29
31
|
ACCEPT_KEY = 'accept'
|
30
32
|
|
33
|
+
DEFAULT_ACCEPT_SET = ['Inline::C']
|
34
|
+
|
31
35
|
def self.default_config
|
32
36
|
super.adopt(
|
33
|
-
REJECT_KEY =>
|
34
|
-
ACCEPT_KEY =>
|
37
|
+
REJECT_KEY => DEFAULT_REJECT_SET,
|
38
|
+
ACCEPT_KEY => DEFAULT_ACCEPT_SET
|
35
39
|
)
|
36
40
|
end
|
37
41
|
|
@@ -54,22 +58,22 @@ module Reek
|
|
54
58
|
|
55
59
|
def consider_variables(context) # :nodoc:
|
56
60
|
context.variable_names.each do |name|
|
57
|
-
next unless is_bad_name?(name)
|
61
|
+
next unless is_bad_name?(name, context)
|
58
62
|
found(context, "has the variable name '#{name}'")
|
59
63
|
end
|
60
64
|
end
|
61
65
|
|
62
66
|
def consider_name(context) # :nodoc:
|
63
67
|
name = context.name
|
64
|
-
return false if
|
65
|
-
return false unless is_bad_name?(name)
|
68
|
+
return false if value(ACCEPT_KEY, context, DEFAULT_ACCEPT_SET).include?(context.to_s) # TODO: fq_name() ?
|
69
|
+
return false unless is_bad_name?(name, context)
|
66
70
|
found(context, "has the name '#{name}'")
|
67
71
|
end
|
68
72
|
|
69
|
-
def is_bad_name?(name) # :nodoc:
|
73
|
+
def is_bad_name?(name, context) # :nodoc:
|
70
74
|
var = name.effective_name
|
71
|
-
return false if var == '*' or
|
72
|
-
|
75
|
+
return false if var == '*' or value(ACCEPT_KEY, context, DEFAULT_ACCEPT_SET).include?(var)
|
76
|
+
value(REJECT_KEY, context, DEFAULT_REJECT_SET).detect {|patt| patt === var}
|
73
77
|
end
|
74
78
|
end
|
75
79
|
end
|
data/lib/reek/sniffer.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
require 'reek/detector_stack'
|
2
|
+
|
3
|
+
# SMELL: Duplication -- all these should be found automagically
|
2
4
|
require 'reek/smells/control_couple'
|
3
5
|
require 'reek/smells/duplication'
|
4
6
|
require 'reek/smells/feature_envy'
|
@@ -7,6 +9,7 @@ require 'reek/smells/long_method'
|
|
7
9
|
require 'reek/smells/long_parameter_list'
|
8
10
|
require 'reek/smells/long_yield_list'
|
9
11
|
require 'reek/smells/nested_iterators'
|
12
|
+
require 'reek/smells/simulated_polymorphism'
|
10
13
|
require 'reek/smells/uncommunicative_name'
|
11
14
|
require 'reek/smells/utility_function'
|
12
15
|
require 'reek/code_parser'
|
@@ -52,6 +55,7 @@ module Reek
|
|
52
55
|
Smells::LongParameterList,
|
53
56
|
Smells::LongYieldList,
|
54
57
|
Smells::NestedIterators,
|
58
|
+
Smells::SimulatedPolymorphism,
|
55
59
|
Smells::UncommunicativeName,
|
56
60
|
Smells::UtilityFunction,
|
57
61
|
]
|
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.14"
|
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-08-20}
|
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/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/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/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/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/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/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/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"]
|
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
|
@@ -33,16 +33,17 @@ end
|
|
33
33
|
describe ReportSection, " as a SortedSet" do
|
34
34
|
it 'should only add a smell once' do
|
35
35
|
rpt = ReportSection.new(''.sniff)
|
36
|
-
rpt << SmellWarning.new(Smells::FeatureEnvy.new, "self", 'too many!')
|
37
|
-
rpt << SmellWarning.new(Smells::FeatureEnvy.new, "self", 'too many!')
|
36
|
+
rpt << SmellWarning.new(Smells::FeatureEnvy.new, "self", 'too many!', false)
|
37
|
+
rpt << SmellWarning.new(Smells::FeatureEnvy.new, "self", 'too many!', false)
|
38
38
|
lines = rpt.smell_list.split("\n")
|
39
39
|
lines.should have(1).lines
|
40
40
|
end
|
41
41
|
|
42
42
|
it 'should not count an identical masked smell' do
|
43
43
|
rpt = ReportSection.new(''.sniff)
|
44
|
-
|
45
|
-
rpt
|
44
|
+
# SMELL: Duplication -- the SmellWarning knows whether to call << or record_masked_smell
|
45
|
+
rpt << SmellWarning.new(Smells::FeatureEnvy.new, "self", 'too many!', false)
|
46
|
+
rpt.record_masked_smell(SmellWarning.new(Smells::FeatureEnvy.new, "self", 'too many!', true))
|
46
47
|
rpt.header.should == 'string -- 1 warning'
|
47
48
|
end
|
48
49
|
end
|
@@ -168,4 +168,25 @@ describe ClassContext do
|
|
168
168
|
element = ClassContext.create(StopContext.new, [:colon2, [:colon2, [:const, :Treetop], :Runtime], :SyntaxNode])
|
169
169
|
element.num_methods.should == 0
|
170
170
|
end
|
171
|
+
|
172
|
+
it 'counts conditionals correctly' do
|
173
|
+
src = <<EOS
|
174
|
+
class Scrunch
|
175
|
+
def first
|
176
|
+
return @field == :sym ? 0 : 3;
|
177
|
+
end
|
178
|
+
def second
|
179
|
+
if @field == :sym
|
180
|
+
@other += " quarts"
|
181
|
+
end
|
182
|
+
end
|
183
|
+
def third
|
184
|
+
raise 'flu!' unless @field == :sym
|
185
|
+
end
|
186
|
+
end
|
187
|
+
EOS
|
188
|
+
|
189
|
+
ctx = ClassContext.from_s(src)
|
190
|
+
ctx.conditionals.length.should == 3
|
191
|
+
end
|
171
192
|
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper.rb'
|
2
|
+
|
3
|
+
require 'reek/configuration'
|
4
|
+
|
5
|
+
include Reek
|
6
|
+
|
7
|
+
describe SmellConfiguration do
|
8
|
+
it 'returns the default value when key not found' do
|
9
|
+
cf = SmellConfiguration.new({})
|
10
|
+
cf.value('fred', nil, 27).should == 27
|
11
|
+
end
|
12
|
+
end
|
@@ -7,8 +7,8 @@ include Reek
|
|
7
7
|
|
8
8
|
describe SmellWarning, 'equality' do
|
9
9
|
before :each do
|
10
|
-
@first = SmellWarning.new(Smells::FeatureEnvy.new, "self", "self")
|
11
|
-
@second = SmellWarning.new(Smells::FeatureEnvy.new, "self", "self")
|
10
|
+
@first = SmellWarning.new(Smells::FeatureEnvy.new, "self", "self", true)
|
11
|
+
@second = SmellWarning.new(Smells::FeatureEnvy.new, "self", "self", false)
|
12
12
|
end
|
13
13
|
|
14
14
|
it 'should hash equal when the smell is the same' do
|
@@ -22,4 +22,32 @@ describe SmellWarning, 'equality' do
|
|
22
22
|
it 'should compare equal when using <=>' do
|
23
23
|
(@first <=> @second).should == 0
|
24
24
|
end
|
25
|
+
|
26
|
+
class CountingReport
|
27
|
+
attr_reader :masked, :non_masked
|
28
|
+
def initialize
|
29
|
+
@masked = @non_masked = 0
|
30
|
+
end
|
31
|
+
def <<(sw)
|
32
|
+
@non_masked += 1
|
33
|
+
end
|
34
|
+
|
35
|
+
def record_masked_smell(sw)
|
36
|
+
@masked += 1
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'reports as masked when masked' do
|
41
|
+
rpt = CountingReport.new
|
42
|
+
@first.report_on(rpt)
|
43
|
+
rpt.masked.should == 1
|
44
|
+
rpt.non_masked.should == 0
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'reports as non-masked when non-masked' do
|
48
|
+
rpt = CountingReport.new
|
49
|
+
@second.report_on(rpt)
|
50
|
+
rpt.masked.should == 0
|
51
|
+
rpt.non_masked.should == 1
|
52
|
+
end
|
25
53
|
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/../../spec_helper.rb'
|
2
2
|
|
3
|
+
require 'reek/configuration'
|
3
4
|
require 'reek/method_context'
|
4
5
|
require 'reek/stop_context'
|
5
6
|
require 'reek/smells/duplication'
|
@@ -65,7 +66,7 @@ end
|
|
65
66
|
describe Duplication, 'when disabled' do
|
66
67
|
before :each do
|
67
68
|
@ctx = MethodContext.new(StopContext.new, [0, :double_thing])
|
68
|
-
@dup = Duplication.new({
|
69
|
+
@dup = Duplication.new({SmellConfiguration::ENABLED_KEY => false})
|
69
70
|
end
|
70
71
|
|
71
72
|
it 'should not report repeated call' do
|
@@ -182,6 +182,21 @@ def report
|
|
182
182
|
@report
|
183
183
|
end
|
184
184
|
EOS
|
185
|
+
|
186
|
+
ruby.should_not reek
|
187
|
+
end
|
188
|
+
|
189
|
+
it 'interprets << correctly' do
|
190
|
+
ruby = <<EOS
|
191
|
+
def report_on(report)
|
192
|
+
if @is_masked
|
193
|
+
report.record_masked_smell(self)
|
194
|
+
else
|
195
|
+
report << self
|
196
|
+
end
|
197
|
+
end
|
198
|
+
EOS
|
199
|
+
|
185
200
|
ruby.should_not reek
|
186
201
|
end
|
187
202
|
end
|
@@ -14,7 +14,7 @@ describe LargeClass, 'checking Class objects' do
|
|
14
14
|
pending('test requires ParseTree') unless ObjectSource.can_parse_objects?
|
15
15
|
class BigOne
|
16
16
|
26.times do |i|
|
17
|
-
define_method "method#{i}".to_sym do
|
17
|
+
define_method "method#{i}x".to_sym do
|
18
18
|
@melting
|
19
19
|
end
|
20
20
|
end
|
@@ -25,12 +25,12 @@ describe LargeClass, 'checking Class objects' do
|
|
25
25
|
it 'should not report short class' do
|
26
26
|
pending('test requires ParseTree') unless ObjectSource.can_parse_objects?
|
27
27
|
class ShortClass
|
28
|
-
def
|
29
|
-
def
|
30
|
-
def
|
31
|
-
def
|
32
|
-
def
|
33
|
-
def
|
28
|
+
def method_a() @var_a; end
|
29
|
+
def method_b() @var_b; end
|
30
|
+
def method_c() @var_c; end
|
31
|
+
def method_d() @var_d; end
|
32
|
+
def method_e() @var_e; end
|
33
|
+
def method_f() @var_f; end
|
34
34
|
end
|
35
35
|
ShortClass.should_not reek
|
36
36
|
end
|
@@ -111,9 +111,10 @@ describe LargeClass, 'checking source code' do
|
|
111
111
|
|
112
112
|
it 'should not report 10 ivars in 2 extensions' do
|
113
113
|
src = <<EOS
|
114
|
-
class Full;def
|
115
|
-
class Full;def
|
114
|
+
class Full;def ivars_a() @aa=@ab=@ac=@ad=@ae; end;end
|
115
|
+
class Full;def ivars_b() @af=@ag=@ah=@ai=@aj; end;end
|
116
116
|
EOS
|
117
|
+
|
117
118
|
src.should_not reek
|
118
119
|
end
|
119
120
|
end
|
@@ -134,11 +135,11 @@ EOS
|
|
134
135
|
it 'should not report 25 methods' do
|
135
136
|
src = <<EOS
|
136
137
|
class Full
|
137
|
-
def
|
138
|
-
def
|
139
|
-
def
|
140
|
-
def
|
141
|
-
def
|
138
|
+
def me01x()3 end;def me02x()3 end;def me03x()3 end;def me04x()3 end;def me05x()3 end
|
139
|
+
def me11x()3 end;def me12x()3 end;def me13x()3 end;def me14x()3 end;def me15x()3 end
|
140
|
+
def me21x()3 end;def me22x()3 end;def me23x()3 end;def me24x()3 end;def me25x()3 end
|
141
|
+
def me31x()3 end;def me32x()3 end;def me33x()3 end;def me34x()3 end;def me35x()3 end
|
142
|
+
def me41x()3 end;def me42x()3 end;def me43x()3 end;def me44x()3 end;def me45x()3 end
|
142
143
|
end
|
143
144
|
EOS
|
144
145
|
src.should_not reek
|
@@ -147,12 +148,12 @@ EOS
|
|
147
148
|
it 'should report 26 methods' do
|
148
149
|
src = <<EOS
|
149
150
|
class Full
|
150
|
-
def
|
151
|
-
def
|
152
|
-
def
|
153
|
-
def
|
154
|
-
def
|
155
|
-
def
|
151
|
+
def me01x()3 end;def me02x()3 end;def me03x()3 end;def me04x()3 end;def me05x()3 end
|
152
|
+
def me11x()3 end;def me12x()3 end;def me13x()3 end;def me14x()3 end;def me15x()3 end
|
153
|
+
def me21x()3 end;def me22x()3 end;def me23x()3 end;def me24x()3 end;def me25x()3 end
|
154
|
+
def me31x()3 end;def me32x()3 end;def me33x()3 end;def me34x()3 end;def me35x()3 end
|
155
|
+
def me41x()3 end;def me42x()3 end;def me43x()3 end;def me44x()3 end;def me45x()3 end
|
156
|
+
def me51x()3 end
|
156
157
|
end
|
157
158
|
EOS
|
158
159
|
src.should reek_of(:LargeClass)
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper.rb'
|
2
|
+
|
3
|
+
require 'reek/smells/simulated_polymorphism'
|
4
|
+
|
5
|
+
include Reek::Smells
|
6
|
+
|
7
|
+
describe SimulatedPolymorphism do
|
8
|
+
it 'should report 3 similar conditions in a class' do
|
9
|
+
src = <<EOS
|
10
|
+
class Scrunch
|
11
|
+
def first
|
12
|
+
return @field == :sym ? 0 : 3;
|
13
|
+
end
|
14
|
+
def second
|
15
|
+
if @field == :sym
|
16
|
+
@other += " quarts"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
def third
|
20
|
+
raise 'flu!' unless @field == :sym
|
21
|
+
end
|
22
|
+
end
|
23
|
+
EOS
|
24
|
+
|
25
|
+
src.should reek_only_of(:SimulatedPolymorphism, /@field == :sym/)
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'should include case statements in the count' do
|
29
|
+
src = <<EOS
|
30
|
+
class Scrunch
|
31
|
+
def first
|
32
|
+
return @field ? 0 : 3;
|
33
|
+
end
|
34
|
+
def second
|
35
|
+
case @field
|
36
|
+
when :sym
|
37
|
+
@other += " quarts"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
def third
|
41
|
+
raise 'flu!' unless @field
|
42
|
+
end
|
43
|
+
end
|
44
|
+
EOS
|
45
|
+
|
46
|
+
src.should reek_only_of(:SimulatedPolymorphism, /@field/)
|
47
|
+
end
|
48
|
+
|
49
|
+
# And count code in superclasses, if we have it
|
50
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/../../spec_helper.rb'
|
2
2
|
|
3
|
-
require 'reek/
|
3
|
+
require 'reek/configuration'
|
4
4
|
require 'reek/smells/duplication'
|
5
5
|
require 'reek/smells/large_class'
|
6
6
|
require 'reek/smells/long_method'
|
@@ -14,8 +14,8 @@ describe SmellDetector, 'configuration' do
|
|
14
14
|
end
|
15
15
|
|
16
16
|
it 'adopts new max_statements value' do
|
17
|
-
@detector.configure_with(
|
18
|
-
@detector.
|
17
|
+
@detector.configure_with(LongMethod::MAX_ALLOWED_STATEMENTS_KEY => 25)
|
18
|
+
@detector.value(LongMethod::MAX_ALLOWED_STATEMENTS_KEY, nil, 0).should == 25
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
@@ -31,7 +31,7 @@ describe SmellDetector, 'when copied' do
|
|
31
31
|
|
32
32
|
it 'should change independently of its parent' do
|
33
33
|
default_max = @detector.max_statements
|
34
|
-
@copy.configure_with(
|
34
|
+
@copy.configure_with(LongMethod::MAX_ALLOWED_STATEMENTS_KEY => 25)
|
35
35
|
@detector.max_statements.should == default_max
|
36
36
|
end
|
37
37
|
end
|
@@ -47,7 +47,7 @@ describe SmellDetector, 'configuration' do
|
|
47
47
|
it 'becomes disabled when disabled' do
|
48
48
|
@detector = LargeClass.new
|
49
49
|
@detector.should be_enabled
|
50
|
-
@detector.configure({'LargeClass' => {
|
50
|
+
@detector.configure({'LargeClass' => {SmellConfiguration::ENABLED_KEY => false}})
|
51
51
|
@detector.should_not be_enabled
|
52
52
|
end
|
53
53
|
end
|
@@ -16,6 +16,9 @@ describe UncommunicativeName, "method name" do
|
|
16
16
|
it 'should report name of the form "x2"' do
|
17
17
|
'def x2(fred) basics(17) end'.should reek_only_of(:UncommunicativeName, /x2/)
|
18
18
|
end
|
19
|
+
it 'should report long name ending in a number' do
|
20
|
+
'def method2(fred) basics(17) end'.should reek_only_of(:UncommunicativeName, /method2/)
|
21
|
+
end
|
19
22
|
end
|
20
23
|
|
21
24
|
describe UncommunicativeName, "field name" do
|
@@ -28,6 +31,9 @@ describe UncommunicativeName, "field name" do
|
|
28
31
|
it 'should report name of the form "x2"' do
|
29
32
|
'class Thing; def simple(fred) @x2 end end'.should reek_only_of(:UncommunicativeName, /@x2/, /Thing/, /variable name/)
|
30
33
|
end
|
34
|
+
it 'should report long name ending in a number' do
|
35
|
+
'class Thing; def simple(fred) @field12 end end'.should reek_only_of(:UncommunicativeName, /@field12/, /Thing/, /variable name/)
|
36
|
+
end
|
31
37
|
it 'should report one-letter fieldname in assignment' do
|
32
38
|
'class Thing; def simple(fred) @x = fred end end'.should reek_only_of(:UncommunicativeName, /@x/, /Thing/, /variable name/)
|
33
39
|
end
|
@@ -43,6 +49,9 @@ describe UncommunicativeName, "local variable name" do
|
|
43
49
|
it 'should report name of the form "x2"' do
|
44
50
|
'def simple(fred) x2 = jim(45) end'.should reek_only_of(:UncommunicativeName, /x2/, /variable name/)
|
45
51
|
end
|
52
|
+
it 'should report long name ending in a number' do
|
53
|
+
'def simple(fred) var123 = jim(45) end'.should reek_only_of(:UncommunicativeName, /var123/, /variable name/)
|
54
|
+
end
|
46
55
|
it 'should report variable name only once' do
|
47
56
|
'def simple(fred) x = jim(45); x = y end'.should reek_only_of(:UncommunicativeName, /x/)
|
48
57
|
end
|
@@ -63,6 +72,9 @@ describe UncommunicativeName, "parameter name" do
|
|
63
72
|
it 'should report name of the form "x2"' do
|
64
73
|
'def help(x2) basics(17) end'.should reek_only_of(:UncommunicativeName, /x2/, /variable name/)
|
65
74
|
end
|
75
|
+
it 'should report long name ending in a number' do
|
76
|
+
'def help(param1) basics(17) end'.should reek_only_of(:UncommunicativeName, /param1/, /variable name/)
|
77
|
+
end
|
66
78
|
end
|
67
79
|
|
68
80
|
describe UncommunicativeName, "block parameter name" do
|
@@ -78,6 +90,7 @@ def bad
|
|
78
90
|
end
|
79
91
|
end
|
80
92
|
EOS
|
93
|
+
|
81
94
|
src.should reek_only_of(:UncommunicativeName, /'x'/)
|
82
95
|
end
|
83
96
|
end
|
@@ -100,6 +113,7 @@ class Thing
|
|
100
113
|
end
|
101
114
|
end
|
102
115
|
EOS
|
116
|
+
|
103
117
|
source.should reek_of(:UncommunicativeName, /'x'/)
|
104
118
|
source.should reek_of(:UncommunicativeName, /'y'/)
|
105
119
|
end
|