kevinrutherford-reek 1.1.3.13 → 1.1.3.14
Sign up to get free protection for your applications and to get access to all the features.
- 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
|