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
data/lib/reek/smell_warning.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require '
|
1
|
+
require 'forwardable'
|
2
2
|
|
3
3
|
module Reek
|
4
4
|
#
|
@@ -6,40 +6,21 @@ module Reek
|
|
6
6
|
#
|
7
7
|
class SmellWarning
|
8
8
|
include Comparable
|
9
|
+
extend Forwardable
|
10
|
+
attr_accessor :smell_detector, :context, :lines, :message, :parameters
|
11
|
+
def_delegators :smell_detector, :smell_category, :smell_type, :source
|
9
12
|
|
10
|
-
def initialize(
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
'source' => source
|
17
|
-
}
|
13
|
+
def initialize(smell_detector, options = {})
|
14
|
+
self.smell_detector = smell_detector
|
15
|
+
self.context = options.fetch(:context, '').to_s
|
16
|
+
self.lines = options.fetch(:lines)
|
17
|
+
self.message = options.fetch(:message)
|
18
|
+
self.parameters = options.fetch(:parameters, {})
|
18
19
|
end
|
19
20
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
# @return [Hash{String => String}]
|
24
|
-
#
|
25
|
-
attr_reader :smell
|
26
|
-
|
27
|
-
def smell_classes() [smell_class, subclass] end
|
28
|
-
def smell_class() @smell.smell_class end
|
29
|
-
def subclass() @smell.smell_subclass end
|
30
|
-
def message() @smell.message end
|
31
|
-
|
32
|
-
#
|
33
|
-
# Details of the smell's location, including its context,
|
34
|
-
# the line numbers on which it occurs and the source file
|
35
|
-
#
|
36
|
-
# @return [Hash{String => String, Array<Number>}]
|
37
|
-
#
|
38
|
-
attr_reader :location
|
39
|
-
|
40
|
-
def context() @location.fetch('context') end
|
41
|
-
def lines() @location.fetch('lines') end
|
42
|
-
def source() @location.fetch('source') end
|
21
|
+
def smell_classes
|
22
|
+
[smell_detector.smell_category, smell_detector.smell_type]
|
23
|
+
end
|
43
24
|
|
44
25
|
def hash
|
45
26
|
sort_key.hash
|
@@ -61,16 +42,17 @@ module Reek
|
|
61
42
|
listener.found_smell(self)
|
62
43
|
end
|
63
44
|
|
64
|
-
def
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
45
|
+
def encode_with(coder)
|
46
|
+
coder.tag = nil
|
47
|
+
coder['smell_category'] = smell_detector.smell_category
|
48
|
+
coder['smell_type'] = smell_detector.smell_type
|
49
|
+
coder['source'] = smell_detector.source
|
50
|
+
coder['context'] = context
|
51
|
+
coder['lines'] = lines
|
52
|
+
coder['message'] = message
|
53
|
+
parameters.each do |key, value|
|
54
|
+
coder[key.to_s] = value
|
55
|
+
end
|
74
56
|
end
|
75
57
|
|
76
58
|
protected
|
@@ -81,7 +63,7 @@ module Reek
|
|
81
63
|
end
|
82
64
|
|
83
65
|
def sort_key
|
84
|
-
[context, message,
|
66
|
+
[context, message, smell_category]
|
85
67
|
end
|
86
68
|
end
|
87
69
|
end
|
@@ -17,12 +17,7 @@ module Reek
|
|
17
17
|
# TODO: Catch attributes declared "by hand"
|
18
18
|
#
|
19
19
|
class Attribute < SmellDetector
|
20
|
-
|
21
|
-
SMELL_SUBCLASS = SMELL_CLASS
|
22
|
-
|
23
|
-
ATTRIBUTE_KEY = 'attribute'
|
24
|
-
|
25
|
-
def self.contexts # :nodoc:
|
20
|
+
def self.contexts # :nodoc:
|
26
21
|
[:class, :module]
|
27
22
|
end
|
28
23
|
|
@@ -36,12 +31,12 @@ module Reek
|
|
36
31
|
# @return [Array<SmellWarning>]
|
37
32
|
#
|
38
33
|
def examine_context(ctx)
|
39
|
-
attributes_in(ctx).map do |
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
34
|
+
attributes_in(ctx).map do |attribute, line|
|
35
|
+
SmellWarning.new self,
|
36
|
+
context: ctx.full_name,
|
37
|
+
lines: [line],
|
38
|
+
message: "declares the attribute #{attribute}",
|
39
|
+
parameters: { name: attribute.to_s }
|
45
40
|
end
|
46
41
|
end
|
47
42
|
|
@@ -12,10 +12,9 @@ module Reek
|
|
12
12
|
# default initializer.
|
13
13
|
#
|
14
14
|
class BooleanParameter < SmellDetector
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
PARAMETER_KEY = 'parameter'
|
15
|
+
def self.smell_category
|
16
|
+
'ControlCouple'
|
17
|
+
end
|
19
18
|
|
20
19
|
#
|
21
20
|
# Checks whether the given method has any Boolean parameters.
|
@@ -25,11 +24,12 @@ module Reek
|
|
25
24
|
def examine_context(method_ctx)
|
26
25
|
method_ctx.parameters.default_assignments.select do |_param, value|
|
27
26
|
[:true, :false].include?(value[0])
|
28
|
-
end.map do |
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
27
|
+
end.map do |parameter, _value|
|
28
|
+
SmellWarning.new self,
|
29
|
+
context: method_ctx.full_name,
|
30
|
+
lines: [method_ctx.exp.line],
|
31
|
+
message: "has boolean parameter '#{parameter}'",
|
32
|
+
parameters: { name: parameter.to_s }
|
33
33
|
end
|
34
34
|
end
|
35
35
|
end
|
@@ -13,12 +13,7 @@ module Reek
|
|
13
13
|
# the context of the test includes all global state).
|
14
14
|
#
|
15
15
|
class ClassVariable < SmellDetector
|
16
|
-
|
17
|
-
SMELL_SUBCLASS = SMELL_CLASS
|
18
|
-
|
19
|
-
VARIABLE_KEY = 'variable'
|
20
|
-
|
21
|
-
def self.contexts # :nodoc:
|
16
|
+
def self.contexts # :nodoc:
|
22
17
|
[:class, :module]
|
23
18
|
end
|
24
19
|
|
@@ -28,13 +23,12 @@ module Reek
|
|
28
23
|
# @return [Array<SmellWarning>]
|
29
24
|
#
|
30
25
|
def examine_context(ctx)
|
31
|
-
class_variables_in(ctx.exp).map do |
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
smell
|
26
|
+
class_variables_in(ctx.exp).map do |variable, lines|
|
27
|
+
SmellWarning.new self,
|
28
|
+
context: ctx.full_name,
|
29
|
+
lines: lines,
|
30
|
+
message: "declares the class variable #{variable}",
|
31
|
+
parameters: { name: variable.to_s }
|
38
32
|
end
|
39
33
|
end
|
40
34
|
|
@@ -41,9 +41,9 @@ module Reek
|
|
41
41
|
# the source code.
|
42
42
|
#
|
43
43
|
class ControlParameter < SmellDetector
|
44
|
-
|
45
|
-
|
46
|
-
|
44
|
+
def self.smell_category
|
45
|
+
'ControlCouple'
|
46
|
+
end
|
47
47
|
|
48
48
|
#
|
49
49
|
# Checks whether the given method chooses its execution path
|
@@ -53,10 +53,11 @@ module Reek
|
|
53
53
|
#
|
54
54
|
def examine_context(ctx)
|
55
55
|
ControlParameterCollector.new(ctx).control_parameters.map do |control_parameter|
|
56
|
-
SmellWarning.new
|
57
|
-
|
58
|
-
|
59
|
-
|
56
|
+
SmellWarning.new self,
|
57
|
+
context: ctx.full_name,
|
58
|
+
lines: control_parameter.lines,
|
59
|
+
message: "is controlled by argument #{control_parameter.name}",
|
60
|
+
parameters: { name: control_parameter.name.to_s }
|
60
61
|
end
|
61
62
|
end
|
62
63
|
|
@@ -73,10 +74,6 @@ module Reek
|
|
73
74
|
@occurences.any?
|
74
75
|
end
|
75
76
|
|
76
|
-
def smell_message
|
77
|
-
"is controlled by argument #{name}"
|
78
|
-
end
|
79
|
-
|
80
77
|
def lines
|
81
78
|
@occurences.map(&:line)
|
82
79
|
end
|
@@ -17,18 +17,6 @@ module Reek
|
|
17
17
|
# the same names that are expected by three or more methods of a class.
|
18
18
|
#
|
19
19
|
class DataClump < SmellDetector
|
20
|
-
SMELL_CLASS = name.split(/::/)[-1]
|
21
|
-
SMELL_SUBCLASS = name.split(/::/)[-1]
|
22
|
-
|
23
|
-
METHODS_KEY = 'methods'
|
24
|
-
OCCURRENCES_KEY = 'occurrences'
|
25
|
-
PARAMETERS_KEY = 'parameters'
|
26
|
-
|
27
|
-
# @private
|
28
|
-
def self.contexts
|
29
|
-
[:class, :module]
|
30
|
-
end
|
31
|
-
|
32
20
|
#
|
33
21
|
# The name of the config field that sets the maximum allowed
|
34
22
|
# copies of any clump. No group of common parameters will be
|
@@ -46,6 +34,10 @@ module Reek
|
|
46
34
|
MIN_CLUMP_SIZE_KEY = 'min_clump_size'
|
47
35
|
DEFAULT_MIN_CLUMP_SIZE = 2
|
48
36
|
|
37
|
+
def self.contexts # :nodoc:
|
38
|
+
[:class, :module]
|
39
|
+
end
|
40
|
+
|
49
41
|
def self.default_config
|
50
42
|
super.merge(
|
51
43
|
MAX_COPIES_KEY => DEFAULT_MAX_COPIES,
|
@@ -62,13 +54,17 @@ module Reek
|
|
62
54
|
@max_copies = value(MAX_COPIES_KEY, ctx, DEFAULT_MAX_COPIES)
|
63
55
|
@min_clump_size = value(MIN_CLUMP_SIZE_KEY, ctx, DEFAULT_MIN_CLUMP_SIZE)
|
64
56
|
MethodGroup.new(ctx, @min_clump_size, @max_copies).clumps.map do |clump, methods|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
57
|
+
print_clump = DataClump.print_clump(clump)
|
58
|
+
SmellWarning.new self,
|
59
|
+
context: ctx.full_name,
|
60
|
+
lines: methods.map(&:line),
|
61
|
+
message: "takes parameters #{print_clump} " \
|
62
|
+
"to #{methods.length} methods",
|
63
|
+
parameters: {
|
64
|
+
parameters: clump.map(&:to_s),
|
65
|
+
count: methods.length,
|
66
|
+
methods: methods.map(&:name)
|
67
|
+
}
|
72
68
|
end
|
73
69
|
end
|
74
70
|
|
@@ -118,11 +114,10 @@ module Reek
|
|
118
114
|
class CandidateMethod
|
119
115
|
def initialize(defn_node)
|
120
116
|
@defn = defn_node
|
121
|
-
@params = defn_node.arg_names.clone.sort { |first, second| first.to_s <=> second.to_s }
|
122
117
|
end
|
123
118
|
|
124
119
|
def arg_names
|
125
|
-
@
|
120
|
+
@arg_names ||= @defn.arg_names.compact.sort
|
126
121
|
end
|
127
122
|
|
128
123
|
def line
|
@@ -17,25 +17,21 @@ module Reek
|
|
17
17
|
# end
|
18
18
|
#
|
19
19
|
class DuplicateMethodCall < SmellDetector
|
20
|
-
SMELL_CLASS = 'Duplication'
|
21
|
-
SMELL_SUBCLASS = name.split(/::/)[-1]
|
22
|
-
|
23
|
-
CALL_KEY = 'call'
|
24
|
-
OCCURRENCES_KEY = 'occurrences'
|
25
|
-
|
26
20
|
# The name of the config field that sets the maximum number of
|
27
21
|
# identical calls to be permitted within any single method.
|
28
22
|
MAX_ALLOWED_CALLS_KEY = 'max_calls'
|
29
|
-
|
30
23
|
DEFAULT_MAX_CALLS = 1
|
31
24
|
|
32
25
|
# The name of the config field that sets the names of any
|
33
26
|
# methods for which identical calls should be to be permitted
|
34
27
|
# within any single method.
|
35
28
|
ALLOW_CALLS_KEY = 'allow_calls'
|
36
|
-
|
37
29
|
DEFAULT_ALLOW_CALLS = []
|
38
30
|
|
31
|
+
def self.smell_category
|
32
|
+
'Duplication'
|
33
|
+
end
|
34
|
+
|
39
35
|
def self.default_config
|
40
36
|
super.merge(
|
41
37
|
MAX_ALLOWED_CALLS_KEY => DEFAULT_MAX_CALLS,
|
@@ -52,11 +48,13 @@ module Reek
|
|
52
48
|
max_allowed_calls = value(MAX_ALLOWED_CALLS_KEY, ctx, DEFAULT_MAX_CALLS)
|
53
49
|
allow_calls = value(ALLOW_CALLS_KEY, ctx, DEFAULT_ALLOW_CALLS)
|
54
50
|
|
55
|
-
CallCollector.new(ctx, max_allowed_calls, allow_calls)
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
51
|
+
collector = CallCollector.new(ctx, max_allowed_calls, allow_calls)
|
52
|
+
collector.smelly_calls.map do |found_call|
|
53
|
+
SmellWarning.new self,
|
54
|
+
context: ctx.full_name,
|
55
|
+
lines: found_call.lines,
|
56
|
+
message: "calls #{found_call.call} #{found_call.occurs} times",
|
57
|
+
parameters: { name: found_call.call, count: found_call.occurs }
|
60
58
|
end
|
61
59
|
end
|
62
60
|
|
@@ -71,11 +69,6 @@ module Reek
|
|
71
69
|
@occurences.push occurence
|
72
70
|
end
|
73
71
|
|
74
|
-
def smell_message
|
75
|
-
multiple = occurs == 2 ? 'twice' : "#{occurs} times"
|
76
|
-
"calls #{call} #{multiple}"
|
77
|
-
end
|
78
|
-
|
79
72
|
def call
|
80
73
|
@call ||= @call_node.format_ruby
|
81
74
|
end
|
@@ -33,11 +33,9 @@ module Reek
|
|
33
33
|
class FeatureEnvy < SmellDetector
|
34
34
|
include ExcludeInitialize
|
35
35
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
RECEIVER_KEY = 'receiver'
|
40
|
-
REFERENCES_KEY = 'references'
|
36
|
+
def self.smell_category
|
37
|
+
'LowCohesion'
|
38
|
+
end
|
41
39
|
|
42
40
|
#
|
43
41
|
# Checks whether the given +context+ includes any code fragment that
|
@@ -48,9 +46,11 @@ module Reek
|
|
48
46
|
def examine_context(method_ctx)
|
49
47
|
method_ctx.envious_receivers.map do |ref, occurs|
|
50
48
|
target = ref.format_ruby
|
51
|
-
SmellWarning.new
|
52
|
-
|
53
|
-
|
49
|
+
SmellWarning.new self,
|
50
|
+
context: method_ctx.full_name,
|
51
|
+
lines: [method_ctx.exp.line],
|
52
|
+
message: "refers to #{target} more than self",
|
53
|
+
parameters: { name: target, count: occurs }
|
54
54
|
end
|
55
55
|
end
|
56
56
|
end
|
@@ -9,12 +9,7 @@ module Reek
|
|
9
9
|
# with a brief comment outlining its responsibilities.
|
10
10
|
#
|
11
11
|
class IrresponsibleModule < SmellDetector
|
12
|
-
|
13
|
-
SMELL_SUBCLASS = SMELL_CLASS
|
14
|
-
|
15
|
-
MODULE_NAME_KEY = 'module_name'
|
16
|
-
|
17
|
-
def self.contexts # :nodoc:
|
12
|
+
def self.contexts # :nodoc:
|
18
13
|
[:class]
|
19
14
|
end
|
20
15
|
|
@@ -30,10 +25,11 @@ module Reek
|
|
30
25
|
def examine_context(ctx)
|
31
26
|
comment = Source::CodeComment.new(ctx.exp.comments)
|
32
27
|
return [] if self.class.descriptive[ctx.full_name] ||= comment.descriptive?
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
28
|
+
[SmellWarning.new(self,
|
29
|
+
context: ctx.full_name,
|
30
|
+
lines: [ctx.exp.line],
|
31
|
+
message: 'has no descriptive comment',
|
32
|
+
parameters: { name: ctx.exp.text_name })]
|
37
33
|
end
|
38
34
|
end
|
39
35
|
end
|
@@ -13,17 +13,9 @@ module Reek
|
|
13
13
|
# many parameters.
|
14
14
|
#
|
15
15
|
class LongParameterList < SmellDetector
|
16
|
-
SMELL_CLASS = 'LongParameterList'
|
17
|
-
SMELL_SUBCLASS = name.split(/::/)[-1]
|
18
|
-
|
19
|
-
PARAMETER_COUNT_KEY = 'parameter_count'
|
20
|
-
|
21
16
|
# The name of the config field that sets the maximum number of
|
22
17
|
# parameters permitted in any method or block.
|
23
18
|
MAX_ALLOWED_PARAMS_KEY = 'max_params'
|
24
|
-
|
25
|
-
# The default value of the +MAX_ALLOWED_PARAMS_KEY+ configuration
|
26
|
-
# value.
|
27
19
|
DEFAULT_MAX_ALLOWED_PARAMS = 3
|
28
20
|
|
29
21
|
def self.default_config
|
@@ -42,13 +34,13 @@ module Reek
|
|
42
34
|
#
|
43
35
|
def examine_context(ctx)
|
44
36
|
@max_allowed_params = value(MAX_ALLOWED_PARAMS_KEY, ctx, DEFAULT_MAX_ALLOWED_PARAMS)
|
45
|
-
|
46
|
-
return [] if
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
37
|
+
count = ctx.exp.arg_names.length
|
38
|
+
return [] if count <= @max_allowed_params
|
39
|
+
[SmellWarning.new(self,
|
40
|
+
context: ctx.full_name,
|
41
|
+
lines: [ctx.exp.line],
|
42
|
+
message: "has #{count} parameters",
|
43
|
+
parameters: { count: count })]
|
52
44
|
end
|
53
45
|
end
|
54
46
|
end
|