reek 1.5.1 → 1.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +9 -0
- data/README.md +54 -5
- data/Rakefile +1 -1
- data/features/command_line_interface/smell_selection.feature +4 -4
- data/features/command_line_interface/smells_count.feature +9 -8
- data/features/configuration_files/masking_smells.feature +16 -51
- data/features/configuration_files/overrides_defaults.feature +1 -1
- data/features/rake_task/rake_task.feature +14 -14
- data/features/reports/reports.feature +21 -19
- data/features/reports/yaml.feature +35 -63
- data/features/samples.feature +55 -54
- data/features/support/env.rb +8 -1
- data/lib/reek/cli/application.rb +22 -7
- data/lib/reek/cli/command.rb +4 -2
- data/lib/reek/cli/help_command.rb +1 -1
- data/lib/reek/cli/options.rb +3 -3
- data/lib/reek/cli/reek_command.rb +4 -8
- data/lib/reek/cli/report/formatter.rb +8 -5
- data/lib/reek/cli/report/report.rb +6 -5
- data/lib/reek/cli/report/strategy.rb +3 -2
- data/lib/reek/cli/version_command.rb +1 -1
- data/lib/reek/configuration/app_configuration.rb +75 -0
- data/lib/reek/configuration/configuration_file_finder.rb +56 -0
- data/lib/reek/core/code_context.rb +2 -6
- data/lib/reek/core/module_context.rb +4 -0
- data/lib/reek/core/smell_repository.rb +5 -3
- data/lib/reek/core/sniffer.rb +12 -8
- data/lib/reek/examiner.rb +7 -6
- data/lib/reek/rake/task.rb +10 -12
- data/lib/reek/smell_warning.rb +25 -43
- data/lib/reek/smells/attribute.rb +7 -12
- data/lib/reek/smells/boolean_parameter.rb +9 -9
- data/lib/reek/smells/class_variable.rb +7 -13
- data/lib/reek/smells/control_parameter.rb +8 -11
- data/lib/reek/smells/data_clump.rb +16 -21
- data/lib/reek/smells/duplicate_method_call.rb +11 -18
- data/lib/reek/smells/feature_envy.rb +8 -8
- data/lib/reek/smells/irresponsible_module.rb +6 -10
- data/lib/reek/smells/long_parameter_list.rb +7 -15
- data/lib/reek/smells/long_yield_list.rb +13 -15
- data/lib/reek/smells/module_initialize.rb +4 -7
- data/lib/reek/smells/nested_iterators.rb +6 -13
- data/lib/reek/smells/nil_check.rb +9 -7
- data/lib/reek/smells/prima_donna_method.rb +5 -7
- data/lib/reek/smells/repeated_conditional.rb +19 -15
- data/lib/reek/smells/smell_detector.rb +21 -1
- data/lib/reek/smells/too_many_instance_variables.rb +9 -16
- data/lib/reek/smells/too_many_methods.rb +10 -17
- data/lib/reek/smells/too_many_statements.rb +14 -14
- data/lib/reek/smells/uncommunicative_method_name.rb +9 -10
- data/lib/reek/smells/uncommunicative_module_name.rb +9 -10
- data/lib/reek/smells/uncommunicative_parameter_name.rb +9 -9
- data/lib/reek/smells/uncommunicative_variable_name.rb +9 -9
- data/lib/reek/smells/unused_parameters.rb +8 -20
- data/lib/reek/smells/utility_function.rb +12 -10
- data/lib/reek/source.rb +0 -1
- data/lib/reek/source/code_comment.rb +1 -0
- data/lib/reek/source/source_code.rb +3 -13
- data/lib/reek/source/source_file.rb +0 -14
- data/lib/reek/source/source_repository.rb +7 -0
- data/lib/reek/spec/should_reek_of.rb +3 -3
- data/lib/reek/spec/should_reek_only_of.rb +2 -2
- data/lib/reek/version.rb +1 -1
- data/reek.gemspec +4 -2
- data/spec/factories/factories.rb +32 -0
- data/spec/matchers/smell_of_matcher.rb +3 -2
- data/spec/reek/cli/report_spec.rb +2 -1
- data/spec/reek/configuration/app_configuration_spec.rb +67 -0
- data/spec/reek/configuration/configuration_file_finder_spec.rb +35 -0
- data/spec/reek/core/code_context_spec.rb +1 -1
- data/spec/reek/core/module_context_spec.rb +5 -1
- data/spec/reek/core/smell_configuration_spec.rb +21 -13
- data/spec/reek/core/warning_collector_spec.rb +4 -1
- data/spec/reek/examiner_spec.rb +19 -1
- data/spec/reek/smell_warning_spec.rb +42 -36
- data/spec/reek/smells/attribute_spec.rb +6 -2
- data/spec/reek/smells/boolean_parameter_spec.rb +11 -12
- data/spec/reek/smells/class_variable_spec.rb +16 -6
- data/spec/reek/smells/control_parameter_spec.rb +17 -19
- data/spec/reek/smells/data_clump_spec.rb +25 -15
- data/spec/reek/smells/duplicate_method_call_spec.rb +18 -12
- data/spec/reek/smells/feature_envy_spec.rb +29 -10
- data/spec/reek/smells/irresponsible_module_spec.rb +7 -7
- data/spec/reek/smells/long_parameter_list_spec.rb +16 -10
- data/spec/reek/smells/long_yield_list_spec.rb +2 -2
- data/spec/reek/smells/module_initialize_spec.rb +26 -0
- data/spec/reek/smells/nested_iterators_spec.rb +21 -10
- data/spec/reek/smells/nil_check_spec.rb +0 -2
- data/spec/reek/smells/prima_donna_method_spec.rb +3 -3
- data/spec/reek/smells/repeated_conditional_spec.rb +0 -26
- data/spec/reek/smells/smell_detector_shared.rb +4 -4
- data/spec/reek/smells/too_many_instance_variables_spec.rb +3 -3
- data/spec/reek/smells/too_many_methods_spec.rb +16 -11
- data/spec/reek/smells/too_many_statements_spec.rb +55 -18
- data/spec/reek/smells/uncommunicative_method_name_spec.rb +3 -2
- data/spec/reek/smells/uncommunicative_module_name_spec.rb +5 -5
- data/spec/reek/smells/uncommunicative_parameter_name_spec.rb +4 -4
- data/spec/reek/smells/uncommunicative_variable_name_spec.rb +28 -21
- data/spec/reek/smells/unused_parameters_spec.rb +3 -5
- data/spec/reek/smells/utility_function_spec.rb +2 -1
- data/spec/reek/source/code_comment_spec.rb +7 -2
- data/spec/reek/source/reference_collector_spec.rb +0 -1
- data/spec/reek/source/sexp_extensions_spec.rb +0 -15
- data/spec/reek/source/source_code_spec.rb +13 -1
- data/spec/reek/spec/should_reek_only_of_spec.rb +22 -10
- data/spec/reek/spec/should_reek_spec.rb +6 -2
- data/spec/samples/minimal_smelly_and_masked/config.reek +7 -0
- data/spec/samples/minimal_smelly_and_masked/minimal_dirty.rb +4 -0
- data/spec/samples/simple_configuration.reek +5 -0
- data/spec/samples/standard_smelly/dirty.rb +8 -0
- data/spec/samples/standard_smelly/minimal_dirty.rb +4 -0
- data/spec/spec_helper.rb +20 -0
- data/tasks/develop.rake +1 -1
- data/tasks/rubocop.rake +5 -0
- metadata +41 -6
- data/lib/reek/config_file_exception.rb +0 -7
- data/lib/reek/smell_description.rb +0 -26
- data/lib/reek/source/config_file.rb +0 -88
- data/spec/reek/smell_description_spec.rb +0 -43
@@ -8,23 +8,17 @@ module Reek
|
|
8
8
|
# passed to a block by a +yield+ call.
|
9
9
|
#
|
10
10
|
class LongYieldList < SmellDetector
|
11
|
-
SMELL_CLASS = 'LongParameterList'
|
12
|
-
SMELL_SUBCLASS = name.split(/::/)[-1]
|
13
|
-
|
14
11
|
# The name of the config field that sets the maximum number of
|
15
12
|
# parameters permitted in any method or block.
|
16
13
|
MAX_ALLOWED_PARAMS_KEY = 'max_params'
|
17
|
-
|
18
|
-
# The default value of the +MAX_ALLOWED_PARAMS_KEY+ configuration
|
19
|
-
# value.
|
20
14
|
DEFAULT_MAX_ALLOWED_PARAMS = 3
|
21
15
|
|
22
|
-
|
16
|
+
def self.smell_category
|
17
|
+
'LongParameterList'
|
18
|
+
end
|
23
19
|
|
24
20
|
def self.default_config
|
25
|
-
super.merge
|
26
|
-
MAX_ALLOWED_PARAMS_KEY => DEFAULT_MAX_ALLOWED_PARAMS
|
27
|
-
)
|
21
|
+
super.merge MAX_ALLOWED_PARAMS_KEY => DEFAULT_MAX_ALLOWED_PARAMS
|
28
22
|
end
|
29
23
|
|
30
24
|
#
|
@@ -33,14 +27,18 @@ module Reek
|
|
33
27
|
# @return [Array<SmellWarning>]
|
34
28
|
#
|
35
29
|
def examine_context(method_ctx)
|
36
|
-
@max_allowed_params = value(MAX_ALLOWED_PARAMS_KEY,
|
30
|
+
@max_allowed_params = value(MAX_ALLOWED_PARAMS_KEY,
|
31
|
+
method_ctx,
|
32
|
+
DEFAULT_MAX_ALLOWED_PARAMS)
|
37
33
|
method_ctx.local_nodes(:yield).select do |yield_node|
|
38
34
|
yield_node.args.length > @max_allowed_params
|
39
35
|
end.map do |yield_node|
|
40
|
-
|
41
|
-
SmellWarning.new
|
42
|
-
|
43
|
-
|
36
|
+
count = yield_node.args.length
|
37
|
+
SmellWarning.new self,
|
38
|
+
context: method_ctx.full_name,
|
39
|
+
lines: [yield_node.line],
|
40
|
+
message: "yields #{count} parameters",
|
41
|
+
parameters: { count: count }
|
44
42
|
end
|
45
43
|
end
|
46
44
|
end
|
@@ -9,10 +9,7 @@ module Reek
|
|
9
9
|
# in a module is usually a bad idea
|
10
10
|
#
|
11
11
|
class ModuleInitialize < SmellDetector
|
12
|
-
|
13
|
-
SMELL_SUBCLASS = SMELL_CLASS
|
14
|
-
|
15
|
-
def self.contexts # :nodoc:
|
12
|
+
def self.contexts # :nodoc:
|
16
13
|
[:module]
|
17
14
|
end
|
18
15
|
|
@@ -25,9 +22,9 @@ module Reek
|
|
25
22
|
module_ctx.local_nodes(:def) do |node| # FIXME: also search for :defs?
|
26
23
|
if node.name.to_s == 'initialize'
|
27
24
|
return [
|
28
|
-
SmellWarning.new(
|
29
|
-
|
30
|
-
|
25
|
+
SmellWarning.new(self, context: module_ctx.full_name,
|
26
|
+
lines: [module_ctx.exp.line],
|
27
|
+
message: 'has initialize method')
|
31
28
|
]
|
32
29
|
end
|
33
30
|
end
|
@@ -9,21 +9,14 @@ module Reek
|
|
9
9
|
# +NestedIterators+ reports failing methods only once.
|
10
10
|
#
|
11
11
|
class NestedIterators < SmellDetector
|
12
|
-
SMELL_CLASS = name.split(/::/)[-1]
|
13
|
-
SMELL_SUBCLASS = SMELL_CLASS
|
14
|
-
# SMELL: should be a subclass of UnnecessaryComplexity
|
15
|
-
NESTING_DEPTH_KEY = 'depth'
|
16
|
-
|
17
12
|
# The name of the config field that sets the maximum depth
|
18
13
|
# of nested iterators to be permitted within any single method.
|
19
14
|
MAX_ALLOWED_NESTING_KEY = 'max_allowed_nesting'
|
20
|
-
|
21
15
|
DEFAULT_MAX_ALLOWED_NESTING = 1
|
22
16
|
|
23
17
|
# The name of the config field that sets the names of any
|
24
18
|
# methods for which nesting should not be considered
|
25
19
|
IGNORE_ITERATORS_KEY = 'ignore_iterators'
|
26
|
-
|
27
20
|
DEFAULT_IGNORE_ITERATORS = []
|
28
21
|
|
29
22
|
def self.default_config
|
@@ -42,11 +35,11 @@ module Reek
|
|
42
35
|
exp, depth = *find_deepest_iterator(ctx)
|
43
36
|
|
44
37
|
if depth && depth > value(MAX_ALLOWED_NESTING_KEY, ctx, DEFAULT_MAX_ALLOWED_NESTING)
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
38
|
+
[SmellWarning.new(self,
|
39
|
+
context: ctx.full_name,
|
40
|
+
lines: [exp.line],
|
41
|
+
message: "contains iterators nested #{depth} deep",
|
42
|
+
parameters: { count: depth })]
|
50
43
|
else
|
51
44
|
[]
|
52
45
|
end
|
@@ -71,7 +64,7 @@ module Reek
|
|
71
64
|
def find_iters_for_iter_node(exp, depth)
|
72
65
|
ignored = ignored_iterator? exp
|
73
66
|
result = find_iters(exp.call, depth) +
|
74
|
-
|
67
|
+
find_iters(exp.block, depth + (ignored ? 0 : 1))
|
75
68
|
result << [exp, depth] unless ignored
|
76
69
|
result
|
77
70
|
end
|
@@ -6,8 +6,9 @@ module Reek
|
|
6
6
|
# Checking for nil is a special kind of type check, and therefore a case of
|
7
7
|
# SimulatedPolymorphism.
|
8
8
|
class NilCheck < SmellDetector
|
9
|
-
|
10
|
-
|
9
|
+
def self.smell_category
|
10
|
+
'SimulatedPolymorphism'
|
11
|
+
end
|
11
12
|
|
12
13
|
def examine_context(ctx)
|
13
14
|
call_node_finder = NodeFinder.new(ctx, :send, NilCallNodeDetector)
|
@@ -15,9 +16,10 @@ module Reek
|
|
15
16
|
smelly_nodes = call_node_finder.smelly_nodes + case_node_finder.smelly_nodes
|
16
17
|
|
17
18
|
smelly_nodes.map do |node|
|
18
|
-
SmellWarning.new
|
19
|
-
|
20
|
-
|
19
|
+
SmellWarning.new self,
|
20
|
+
context: ctx.full_name,
|
21
|
+
lines: [node.line],
|
22
|
+
message: 'performs a nil-check.'
|
21
23
|
end
|
22
24
|
end
|
23
25
|
|
@@ -50,10 +52,10 @@ module Reek
|
|
50
52
|
end
|
51
53
|
|
52
54
|
def nil_comparison?(call)
|
53
|
-
|
55
|
+
comparison_call?(call) && involves_nil?(call)
|
54
56
|
end
|
55
57
|
|
56
|
-
def
|
58
|
+
def comparison_call?(call)
|
57
59
|
comparison_methods.include? call.method_name
|
58
60
|
end
|
59
61
|
|
@@ -23,10 +23,7 @@ module Reek
|
|
23
23
|
# Such a method is called PrimaDonnaMethod and is reported as a smell.
|
24
24
|
#
|
25
25
|
class PrimaDonnaMethod < SmellDetector
|
26
|
-
|
27
|
-
SMELL_SUBCLASS = smell_class_name
|
28
|
-
|
29
|
-
def self.contexts
|
26
|
+
def self.contexts # :nodoc:
|
30
27
|
[:class]
|
31
28
|
end
|
32
29
|
|
@@ -39,9 +36,10 @@ module Reek
|
|
39
36
|
end
|
40
37
|
next if version_without_bang
|
41
38
|
|
42
|
-
SmellWarning.new
|
43
|
-
|
44
|
-
|
39
|
+
SmellWarning.new self,
|
40
|
+
context: ctx.full_name,
|
41
|
+
lines: [ctx.exp.line],
|
42
|
+
message: "has prima donna method `#{method_sexp.name}`"
|
45
43
|
end.compact
|
46
44
|
end
|
47
45
|
end
|
@@ -6,8 +6,10 @@ module Reek
|
|
6
6
|
#
|
7
7
|
# Simulated Polymorphism occurs when
|
8
8
|
# * code uses a case statement (especially on a type field);
|
9
|
-
# * or code has several if statements in a row
|
10
|
-
#
|
9
|
+
# * or code has several if statements in a row
|
10
|
+
# (especially if they're comparing against the same value);
|
11
|
+
# * or code uses instance_of?, kind_of?, is_a?, or ===
|
12
|
+
# to decide what type it's working with;
|
11
13
|
# * or multiple conditionals in different places test the same value.
|
12
14
|
#
|
13
15
|
# Conditional code is hard to read and understand, because the reader must
|
@@ -21,20 +23,21 @@ module Reek
|
|
21
23
|
# testing the same value throughout a single class.
|
22
24
|
#
|
23
25
|
class RepeatedConditional < SmellDetector
|
24
|
-
|
25
|
-
|
26
|
+
# The name of the config field that sets the maximum number of
|
27
|
+
# identical conditionals permitted within any single class.
|
28
|
+
MAX_IDENTICAL_IFS_KEY = 'max_ifs'
|
29
|
+
DEFAULT_MAX_IFS = 2
|
30
|
+
|
31
|
+
def self.smell_category
|
32
|
+
'SimulatedPolymorphism'
|
33
|
+
end
|
34
|
+
|
26
35
|
BLOCK_GIVEN_CONDITION = AST::Node.new(:send, [nil, :block_given?])
|
27
36
|
|
28
37
|
def self.contexts # :nodoc:
|
29
38
|
[:class]
|
30
39
|
end
|
31
40
|
|
32
|
-
# The name of the config field that sets the maximum number of
|
33
|
-
# identical conditionals permitted within any single class.
|
34
|
-
MAX_IDENTICAL_IFS_KEY = 'max_ifs'
|
35
|
-
|
36
|
-
DEFAULT_MAX_IFS = 2
|
37
|
-
|
38
41
|
def self.default_config
|
39
42
|
super.merge(MAX_IDENTICAL_IFS_KEY => DEFAULT_MAX_IFS)
|
40
43
|
end
|
@@ -50,11 +53,12 @@ module Reek
|
|
50
53
|
lines.length > @max_identical_ifs
|
51
54
|
end.map do |key, lines|
|
52
55
|
occurs = lines.length
|
53
|
-
|
54
|
-
SmellWarning.new
|
55
|
-
|
56
|
-
|
57
|
-
|
56
|
+
expression = key.format_ruby
|
57
|
+
SmellWarning.new self,
|
58
|
+
context: ctx.full_name,
|
59
|
+
lines: lines,
|
60
|
+
message: "tests #{expression} at least #{occurs} times",
|
61
|
+
parameters: { name: expression, count: occurs }
|
58
62
|
end
|
59
63
|
end
|
60
64
|
|
@@ -14,6 +14,8 @@ module Reek
|
|
14
14
|
# Shared responsibilities of all smell detectors.
|
15
15
|
#
|
16
16
|
class SmellDetector
|
17
|
+
attr_reader :source, :smell_category, :smell_type
|
18
|
+
|
17
19
|
# The name of the config field that lists the names of code contexts
|
18
20
|
# that should not be checked. Add this field to the config for each
|
19
21
|
# smell that should ignore this code element.
|
@@ -34,8 +36,26 @@ module Reek
|
|
34
36
|
EXCLUDE_KEY => DEFAULT_EXCLUDE_SET.dup
|
35
37
|
}
|
36
38
|
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def smell_category
|
42
|
+
self.class.smell_category
|
43
|
+
end
|
44
|
+
|
45
|
+
def smell_type
|
46
|
+
self.class.smell_type
|
47
|
+
end
|
48
|
+
|
49
|
+
class << self
|
50
|
+
def smell_category
|
51
|
+
@smell_category ||= default_smell_category
|
52
|
+
end
|
53
|
+
|
54
|
+
def smell_type
|
55
|
+
@smell_type ||= default_smell_category
|
56
|
+
end
|
37
57
|
|
38
|
-
def
|
58
|
+
def default_smell_category
|
39
59
|
name.split(/::/)[-1]
|
40
60
|
end
|
41
61
|
end
|
@@ -11,16 +11,15 @@ module Reek
|
|
11
11
|
# configurable number of instance variables.
|
12
12
|
#
|
13
13
|
class TooManyInstanceVariables < SmellDetector
|
14
|
-
SMELL_CLASS = 'LargeClass'
|
15
|
-
SMELL_SUBCLASS = name.split(/::/)[-1]
|
16
|
-
IVAR_COUNT_KEY = 'ivar_count'
|
17
|
-
|
18
14
|
# The name of the config field that sets the maximum number of instance
|
19
15
|
# variables permitted in a class.
|
20
16
|
MAX_ALLOWED_IVARS_KEY = 'max_instance_variables'
|
21
|
-
|
22
17
|
DEFAULT_MAX_IVARS = 9
|
23
18
|
|
19
|
+
def self.smell_category
|
20
|
+
'LargeClass'
|
21
|
+
end
|
22
|
+
|
24
23
|
def self.contexts # :nodoc:
|
25
24
|
[:class]
|
26
25
|
end
|
@@ -39,19 +38,13 @@ module Reek
|
|
39
38
|
#
|
40
39
|
def examine_context(ctx)
|
41
40
|
@max_allowed_ivars = value(MAX_ALLOWED_IVARS_KEY, ctx, DEFAULT_MAX_IVARS)
|
42
|
-
check_num_ivars(ctx)
|
43
|
-
end
|
44
|
-
|
45
|
-
private
|
46
|
-
|
47
|
-
def check_num_ivars(ctx) # :nodoc:
|
48
41
|
count = ctx.local_nodes(:ivasgn).map { |ivasgn| ivasgn[1] }.uniq.length
|
49
42
|
return [] if count <= @max_allowed_ivars
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
43
|
+
[SmellWarning.new(self,
|
44
|
+
context: ctx.full_name,
|
45
|
+
lines: [ctx.exp.line],
|
46
|
+
message: "has at least #{count} instance variables",
|
47
|
+
parameters: { count: count })]
|
55
48
|
end
|
56
49
|
end
|
57
50
|
end
|
@@ -13,17 +13,16 @@ module Reek
|
|
13
13
|
# modules.
|
14
14
|
#
|
15
15
|
class TooManyMethods < SmellDetector
|
16
|
-
SMELL_CLASS = 'LargeClass'
|
17
|
-
SMELL_SUBCLASS = name.split(/::/)[-1]
|
18
|
-
METHOD_COUNT_KEY = 'method_count'
|
19
|
-
|
20
16
|
# The name of the config field that sets the maximum number of methods
|
21
17
|
# permitted in a class.
|
22
18
|
MAX_ALLOWED_METHODS_KEY = 'max_methods'
|
23
|
-
|
24
19
|
DEFAULT_MAX_METHODS = 25
|
25
20
|
|
26
|
-
def self.
|
21
|
+
def self.smell_category
|
22
|
+
'LargeClass'
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.contexts # :nodoc:
|
27
26
|
[:class]
|
28
27
|
end
|
29
28
|
|
@@ -41,19 +40,13 @@ module Reek
|
|
41
40
|
#
|
42
41
|
def examine_context(ctx)
|
43
42
|
@max_allowed_methods = value(MAX_ALLOWED_METHODS_KEY, ctx, DEFAULT_MAX_METHODS)
|
44
|
-
check_num_methods(ctx)
|
45
|
-
end
|
46
|
-
|
47
|
-
private
|
48
|
-
|
49
|
-
def check_num_methods(ctx) # :nodoc:
|
50
43
|
actual = ctx.node_instance_methods.length
|
51
44
|
return [] if actual <= @max_allowed_methods
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
45
|
+
[SmellWarning.new(self,
|
46
|
+
context: ctx.full_name,
|
47
|
+
lines: [ctx.exp.line],
|
48
|
+
message: "has at least #{actual} methods",
|
49
|
+
parameters: { count: actual })]
|
57
50
|
end
|
58
51
|
end
|
59
52
|
end
|
@@ -9,17 +9,15 @@ module Reek
|
|
9
9
|
# +TooManyStatements+ reports any method with more than 5 statements.
|
10
10
|
#
|
11
11
|
class TooManyStatements < SmellDetector
|
12
|
-
SMELL_CLASS = 'LongMethod'
|
13
|
-
SMELL_SUBCLASS = name.split(/::/)[-1]
|
14
|
-
|
15
|
-
STATEMENT_COUNT_KEY = 'statement_count'
|
16
|
-
|
17
12
|
# The name of the config field that sets the maximum number of
|
18
13
|
# statements permitted in any method.
|
19
14
|
MAX_ALLOWED_STATEMENTS_KEY = 'max_statements'
|
20
|
-
|
21
15
|
DEFAULT_MAX_STATEMENTS = 5
|
22
16
|
|
17
|
+
def self.smell_category
|
18
|
+
'LongMethod'
|
19
|
+
end
|
20
|
+
|
23
21
|
def self.default_config
|
24
22
|
super.merge(
|
25
23
|
MAX_ALLOWED_STATEMENTS_KEY => DEFAULT_MAX_STATEMENTS,
|
@@ -33,14 +31,16 @@ module Reek
|
|
33
31
|
# @return [Array<SmellWarning>]
|
34
32
|
#
|
35
33
|
def examine_context(ctx)
|
36
|
-
@max_allowed_statements = value(MAX_ALLOWED_STATEMENTS_KEY,
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
34
|
+
@max_allowed_statements = value(MAX_ALLOWED_STATEMENTS_KEY,
|
35
|
+
ctx,
|
36
|
+
DEFAULT_MAX_STATEMENTS)
|
37
|
+
count = ctx.num_statements
|
38
|
+
return [] if count <= @max_allowed_statements
|
39
|
+
[SmellWarning.new(self,
|
40
|
+
context: ctx.full_name,
|
41
|
+
lines: [ctx.exp.line],
|
42
|
+
message: "has approx #{count} statements",
|
43
|
+
parameters: { count: count })]
|
44
44
|
end
|
45
45
|
end
|
46
46
|
end
|
@@ -17,23 +17,21 @@ module Reek
|
|
17
17
|
# * names ending with a number
|
18
18
|
#
|
19
19
|
class UncommunicativeMethodName < SmellDetector
|
20
|
-
SMELL_CLASS = 'UncommunicativeName'
|
21
|
-
SMELL_SUBCLASS = name.split(/::/)[-1]
|
22
|
-
METHOD_NAME_KEY = 'method_name'
|
23
|
-
|
24
20
|
# The name of the config field that lists the regexps of
|
25
21
|
# smelly names to be reported.
|
26
22
|
REJECT_KEY = 'reject'
|
27
|
-
|
28
23
|
DEFAULT_REJECT_SET = [/^[a-z]$/, /[0-9]$/, /[A-Z]/]
|
29
24
|
|
30
25
|
# The name of the config field that lists the specific names that are
|
31
26
|
# to be treated as exceptions; these names will not be reported as
|
32
27
|
# uncommunicative.
|
33
28
|
ACCEPT_KEY = 'accept'
|
34
|
-
|
35
29
|
DEFAULT_ACCEPT_SET = []
|
36
30
|
|
31
|
+
def self.smell_category
|
32
|
+
'UncommunicativeName'
|
33
|
+
end
|
34
|
+
|
37
35
|
def self.default_config
|
38
36
|
super.merge(
|
39
37
|
REJECT_KEY => DEFAULT_REJECT_SET,
|
@@ -54,10 +52,11 @@ module Reek
|
|
54
52
|
var = name.gsub(/^[@\*\&]*/, '')
|
55
53
|
return [] if @accept_names.include?(var)
|
56
54
|
return [] unless @reject_names.find { |patt| patt =~ var }
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
55
|
+
[SmellWarning.new(self,
|
56
|
+
context: ctx.full_name,
|
57
|
+
lines: [ctx.exp.line],
|
58
|
+
message: "has the name '#{name}'",
|
59
|
+
parameters: { name: name })]
|
61
60
|
end
|
62
61
|
end
|
63
62
|
end
|