reek 3.3.1 → 3.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +4 -0
- data/CHANGELOG.md +6 -0
- data/CONTRIBUTING.md +3 -0
- data/README.md +12 -4
- data/Rakefile +1 -0
- data/config/defaults.reek +1 -2
- data/docs/Nested-Iterators.md +6 -1
- data/docs/Smell-Suppression.md +69 -5
- data/docs/Uncommunicative-Module-Name.md +1 -1
- data/docs/Utility-Function.md +13 -1
- data/docs/style-guide.md +18 -0
- data/docs/templates/default/docstring/html/public_api_marker.erb +3 -0
- data/docs/templates/default/docstring/setup.rb +41 -0
- data/docs/templates/default/fulldoc/html/css/common.css +1 -0
- data/docs/yard_plugin.rb +2 -0
- data/features/command_line_interface/smell_selection.feature +1 -0
- data/features/configuration_files/masking_smells.feature +12 -0
- data/features/samples.feature +27 -26
- data/features/step_definitions/sample_file_steps.rb +25 -30
- data/lib/reek/ast/ast_node_class_map.rb +1 -1
- data/lib/reek/ast/node.rb +3 -4
- data/lib/reek/ast/object_refs.rb +2 -2
- data/lib/reek/ast/reference_collector.rb +0 -1
- data/lib/reek/ast/sexp_extensions.rb +1 -2
- data/lib/reek/ast/sexp_formatter.rb +1 -2
- data/lib/reek/cli/application.rb +0 -1
- data/lib/reek/cli/command.rb +0 -1
- data/lib/reek/cli/input.rb +2 -1
- data/lib/reek/cli/option_interpreter.rb +0 -1
- data/lib/reek/cli/options.rb +3 -1
- data/lib/reek/cli/reek_command.rb +0 -1
- data/lib/reek/cli/silencer.rb +4 -4
- data/lib/reek/cli/warning_collector.rb +0 -1
- data/lib/reek/code_comment.rb +6 -11
- data/lib/reek/configuration/app_configuration.rb +0 -3
- data/lib/reek/configuration/configuration_file_finder.rb +4 -1
- data/lib/reek/configuration/configuration_validator.rb +1 -0
- data/lib/reek/configuration/directory_directives.rb +4 -0
- data/lib/reek/configuration/excluded_paths.rb +2 -1
- data/lib/reek/context/code_context.rb +11 -4
- data/lib/reek/context/method_context.rb +1 -6
- data/lib/reek/context/module_context.rb +0 -1
- data/lib/reek/context/root_context.rb +0 -1
- data/lib/reek/context/singleton_method_context.rb +0 -1
- data/lib/reek/examiner.rb +15 -15
- data/lib/reek/rake/task.rb +14 -0
- data/lib/reek/report.rb +0 -8
- data/lib/reek/report/formatter.rb +13 -12
- data/lib/reek/report/heading_formatter.rb +2 -1
- data/lib/reek/report/location_formatter.rb +0 -3
- data/lib/reek/report/report.rb +34 -14
- data/lib/reek/smells/attribute.rb +6 -6
- data/lib/reek/smells/boolean_parameter.rb +8 -8
- data/lib/reek/smells/class_variable.rb +7 -6
- data/lib/reek/smells/control_parameter.rb +8 -7
- data/lib/reek/smells/data_clump.rb +18 -20
- data/lib/reek/smells/duplicate_method_call.rb +10 -6
- data/lib/reek/smells/feature_envy.rb +17 -9
- data/lib/reek/smells/irresponsible_module.rb +6 -6
- data/lib/reek/smells/long_parameter_list.rb +7 -7
- data/lib/reek/smells/long_yield_list.rb +10 -9
- data/lib/reek/smells/module_initialize.rb +7 -6
- data/lib/reek/smells/nested_iterators.rb +5 -6
- data/lib/reek/smells/nil_check.rb +4 -5
- data/lib/reek/smells/prima_donna_method.rb +5 -5
- data/lib/reek/smells/repeated_conditional.rb +9 -6
- data/lib/reek/smells/smell_configuration.rb +1 -7
- data/lib/reek/smells/smell_detector.rb +28 -25
- data/lib/reek/smells/smell_repository.rb +18 -19
- data/lib/reek/smells/smell_warning.rb +34 -21
- data/lib/reek/smells/too_many_instance_variables.rb +5 -6
- data/lib/reek/smells/too_many_methods.rb +6 -6
- data/lib/reek/smells/too_many_statements.rb +5 -6
- data/lib/reek/smells/uncommunicative_method_name.rb +6 -6
- data/lib/reek/smells/uncommunicative_module_name.rb +36 -22
- data/lib/reek/smells/uncommunicative_parameter_name.rb +27 -19
- data/lib/reek/smells/uncommunicative_variable_name.rb +13 -7
- data/lib/reek/smells/unused_parameters.rb +10 -9
- data/lib/reek/smells/utility_function.rb +22 -11
- data/lib/reek/source/source_code.rb +11 -12
- data/lib/reek/source/source_locator.rb +6 -1
- data/lib/reek/spec.rb +11 -0
- data/lib/reek/spec/should_reek.rb +0 -3
- data/lib/reek/spec/should_reek_of.rb +1 -1
- data/lib/reek/spec/should_reek_only_of.rb +0 -1
- data/lib/reek/tree_dresser.rb +3 -1
- data/lib/reek/tree_walker.rb +4 -5
- data/lib/reek/version.rb +4 -1
- data/reek.gemspec +1 -1
- data/spec/factories/factories.rb +17 -6
- data/spec/quality/reek_source_spec.rb +3 -1
- data/spec/reek/cli/warning_collector_spec.rb +3 -2
- data/spec/reek/code_comment_spec.rb +8 -10
- data/spec/reek/configuration/directory_directives_spec.rb +2 -2
- data/spec/reek/configuration/excluded_paths_spec.rb +2 -2
- data/spec/reek/context/method_context_spec.rb +0 -26
- data/spec/reek/report/json_report_spec.rb +83 -6
- data/spec/reek/report/yaml_report_spec.rb +76 -6
- data/spec/reek/smells/attribute_spec.rb +1 -1
- data/spec/reek/smells/boolean_parameter_spec.rb +2 -3
- data/spec/reek/smells/class_variable_spec.rb +1 -1
- data/spec/reek/smells/control_parameter_spec.rb +1 -1
- data/spec/reek/smells/data_clump_spec.rb +1 -1
- data/spec/reek/smells/duplicate_method_call_spec.rb +1 -1
- data/spec/reek/smells/feature_envy_spec.rb +1 -0
- data/spec/reek/smells/irresponsible_module_spec.rb +1 -1
- data/spec/reek/smells/long_parameter_list_spec.rb +1 -1
- data/spec/reek/smells/long_yield_list_spec.rb +1 -1
- data/spec/reek/smells/nested_iterators_spec.rb +1 -1
- data/spec/reek/smells/repeated_conditional_spec.rb +1 -1
- data/spec/reek/smells/smell_configuration_spec.rb +9 -9
- data/spec/reek/smells/smell_detector_shared.rb +0 -9
- data/spec/reek/smells/smell_repository_spec.rb +1 -8
- data/spec/reek/smells/smell_warning_spec.rb +3 -2
- data/spec/reek/smells/too_many_instance_variables_spec.rb +1 -1
- data/spec/reek/smells/too_many_methods_spec.rb +2 -4
- data/spec/reek/smells/uncommunicative_method_name_spec.rb +1 -1
- data/spec/reek/smells/uncommunicative_module_name_spec.rb +22 -5
- data/spec/reek/smells/uncommunicative_parameter_name_spec.rb +1 -1
- data/spec/reek/smells/uncommunicative_variable_name_spec.rb +1 -1
- data/spec/reek/smells/utility_function_spec.rb +49 -0
- metadata +9 -5
@@ -7,7 +7,6 @@ module Reek
|
|
7
7
|
# SimulatedPolymorphism.
|
8
8
|
#
|
9
9
|
# See {file:docs/Nil-Check.md} for details.
|
10
|
-
# @api private
|
11
10
|
class NilCheck < SmellDetector
|
12
11
|
def self.smell_category
|
13
12
|
'SimulatedPolymorphism'
|
@@ -19,10 +18,10 @@ module Reek
|
|
19
18
|
smelly_nodes = call_node_finder.smelly_nodes + case_node_finder.smelly_nodes
|
20
19
|
|
21
20
|
smelly_nodes.map do |node|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
21
|
+
smell_warning(
|
22
|
+
context: ctx,
|
23
|
+
lines: [node.line],
|
24
|
+
message: 'performs a nil-check')
|
26
25
|
end
|
27
26
|
end
|
28
27
|
|
@@ -23,7 +23,6 @@ module Reek
|
|
23
23
|
# Such a method is called PrimaDonnaMethod and is reported as a smell.
|
24
24
|
#
|
25
25
|
# See {file:docs/Prima-Donna-Method.md} for details.
|
26
|
-
# @api private
|
27
26
|
class PrimaDonnaMethod < SmellDetector
|
28
27
|
def self.contexts # :nodoc:
|
29
28
|
[:class]
|
@@ -37,6 +36,7 @@ module Reek
|
|
37
36
|
|
38
37
|
private
|
39
38
|
|
39
|
+
# :reek:FeatureEnvy
|
40
40
|
def check_for_smells(method_sexp, ctx)
|
41
41
|
return unless method_sexp.ends_with_bang?
|
42
42
|
|
@@ -46,10 +46,10 @@ module Reek
|
|
46
46
|
|
47
47
|
return if version_without_bang
|
48
48
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
49
|
+
smell_warning(
|
50
|
+
context: ctx,
|
51
|
+
lines: [ctx.exp.line],
|
52
|
+
message: "has prima donna method `#{method_sexp.name}`")
|
53
53
|
end
|
54
54
|
end
|
55
55
|
end
|
@@ -24,7 +24,6 @@ module Reek
|
|
24
24
|
# testing the same value throughout a single class.
|
25
25
|
#
|
26
26
|
# See {file:docs/Repeated-Conditional.md} for details.
|
27
|
-
# @api private
|
28
27
|
class RepeatedConditional < SmellDetector
|
29
28
|
# The name of the config field that sets the maximum number of
|
30
29
|
# identical conditionals permitted within any single class.
|
@@ -50,6 +49,8 @@ module Reek
|
|
50
49
|
#
|
51
50
|
# @return [Array<SmellWarning>]
|
52
51
|
#
|
52
|
+
# :reek:TooManyStatements: { max_statements: 6 }
|
53
|
+
# :reek:DuplicateMethodCall: { max_calls: 2 }
|
53
54
|
def examine_context(ctx)
|
54
55
|
max_identical_ifs = value(MAX_IDENTICAL_IFS_KEY, ctx, DEFAULT_MAX_IFS)
|
55
56
|
conditional_counts(ctx).select do |_key, lines|
|
@@ -57,11 +58,11 @@ module Reek
|
|
57
58
|
end.map do |key, lines|
|
58
59
|
occurs = lines.length
|
59
60
|
expression = key.format_to_ruby
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
61
|
+
smell_warning(
|
62
|
+
context: ctx,
|
63
|
+
lines: lines,
|
64
|
+
message: "tests #{expression} at least #{occurs} times",
|
65
|
+
parameters: { name: expression, count: occurs })
|
65
66
|
end
|
66
67
|
end
|
67
68
|
|
@@ -70,6 +71,8 @@ module Reek
|
|
70
71
|
# the given syntax tree together with the number of times each
|
71
72
|
# occurs. Ignores nested classes and modules.
|
72
73
|
#
|
74
|
+
# :reek:TooManyStatements: { max_statements: 9 }
|
75
|
+
# :reek:FeatureEnvy
|
73
76
|
def conditional_counts(sexp)
|
74
77
|
result = Hash.new { |hash, key| hash[key] = [] }
|
75
78
|
collector = proc do |node|
|
@@ -5,7 +5,6 @@ module Reek
|
|
5
5
|
#
|
6
6
|
# Represents a single set of configuration options for a smell detector
|
7
7
|
#
|
8
|
-
# @api private
|
9
8
|
class SmellConfiguration
|
10
9
|
# The name of the config field that specifies whether a smell is
|
11
10
|
# enabled. Set to +true+ or +false+.
|
@@ -19,14 +18,10 @@ module Reek
|
|
19
18
|
@options = hash
|
20
19
|
end
|
21
20
|
|
22
|
-
def merge
|
21
|
+
def merge(new_options)
|
23
22
|
options.merge!(new_options)
|
24
23
|
end
|
25
24
|
|
26
|
-
#
|
27
|
-
# Is this smell detector active?
|
28
|
-
#--
|
29
|
-
# SMELL: Getter
|
30
25
|
def enabled?
|
31
26
|
options[ENABLED_KEY]
|
32
27
|
end
|
@@ -52,7 +47,6 @@ module Reek
|
|
52
47
|
#
|
53
48
|
# A set of context-specific overrides for smell detectors.
|
54
49
|
#
|
55
|
-
# @api private
|
56
50
|
class Overrides
|
57
51
|
def initialize(hash)
|
58
52
|
@hash = hash
|
@@ -12,10 +12,9 @@ module Reek
|
|
12
12
|
# - {file:README.md}
|
13
13
|
# for details.
|
14
14
|
#
|
15
|
-
#
|
15
|
+
# :reek:TooManyMethods: { max_methods: 19 }
|
16
|
+
# :reek:TooManyInstanceVariables: { max_instance_variables: 5 }
|
16
17
|
class SmellDetector
|
17
|
-
attr_reader :source
|
18
|
-
|
19
18
|
# The name of the config field that lists the names of code contexts
|
20
19
|
# that should not be checked. Add this field to the config for each
|
21
20
|
# smell that should ignore this code element.
|
@@ -30,6 +29,7 @@ module Reek
|
|
30
29
|
[:def, :defs]
|
31
30
|
end
|
32
31
|
|
32
|
+
# :reek:UtilityFunction
|
33
33
|
def default_config
|
34
34
|
{
|
35
35
|
SmellConfiguration::ENABLED_KEY => true,
|
@@ -74,10 +74,8 @@ module Reek
|
|
74
74
|
end
|
75
75
|
end
|
76
76
|
|
77
|
-
|
78
|
-
|
79
|
-
def initialize(source, config = self.class.default_config)
|
80
|
-
@source = source
|
77
|
+
def initialize(config = {})
|
78
|
+
config = self.class.default_config.merge(config)
|
81
79
|
@config = SmellConfiguration.new(config)
|
82
80
|
@smells_found = []
|
83
81
|
end
|
@@ -87,15 +85,6 @@ module Reek
|
|
87
85
|
self.class.contexts.each { |ctx| hooks[ctx] << self }
|
88
86
|
end
|
89
87
|
|
90
|
-
# SMELL: Getter (only used in 1 test)
|
91
|
-
def enabled?
|
92
|
-
config.enabled?
|
93
|
-
end
|
94
|
-
|
95
|
-
def configure_with(new_config)
|
96
|
-
config.merge!(new_config)
|
97
|
-
end
|
98
|
-
|
99
88
|
def examine(context)
|
100
89
|
return unless enabled_for? context
|
101
90
|
return if exception?(context)
|
@@ -104,16 +93,23 @@ module Reek
|
|
104
93
|
self.smells_found += sm
|
105
94
|
end
|
106
95
|
|
107
|
-
def
|
108
|
-
|
96
|
+
def report_on(report)
|
97
|
+
smells_found.each { |smell| smell.report_on(report) }
|
109
98
|
end
|
110
99
|
|
111
100
|
def exception?(context)
|
112
101
|
context.matches?(value(EXCLUDE_KEY, context, DEFAULT_EXCLUDE_SET))
|
113
102
|
end
|
114
103
|
|
115
|
-
|
116
|
-
|
104
|
+
protected
|
105
|
+
|
106
|
+
# NOTE: Needs to be protected so += works for Ruby < 2.2
|
107
|
+
attr_accessor :smells_found
|
108
|
+
|
109
|
+
private
|
110
|
+
|
111
|
+
def enabled_for?(context)
|
112
|
+
config.enabled? && config_for(context)[SmellConfiguration::ENABLED_KEY] != false
|
117
113
|
end
|
118
114
|
|
119
115
|
def value(key, ctx, fall_back)
|
@@ -124,11 +120,18 @@ module Reek
|
|
124
120
|
ctx.config_for(self.class)
|
125
121
|
end
|
126
122
|
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
123
|
+
# :reek:FeatureEnvy
|
124
|
+
def smell_warning(options = {})
|
125
|
+
context = options.fetch(:context)
|
126
|
+
exp = context.exp
|
127
|
+
ctx_source = exp.loc.expression.source_buffer.name
|
128
|
+
SmellWarning.new(self,
|
129
|
+
source: ctx_source,
|
130
|
+
context: context.full_name,
|
131
|
+
lines: options.fetch(:lines),
|
132
|
+
message: options.fetch(:message),
|
133
|
+
parameters: options.fetch(:parameters, {}))
|
134
|
+
end
|
132
135
|
|
133
136
|
private_attr_reader :config
|
134
137
|
end
|
@@ -7,50 +7,49 @@ module Reek
|
|
7
7
|
#
|
8
8
|
# Contains all the existing smells and exposes operations on them.
|
9
9
|
#
|
10
|
-
# @api private
|
11
10
|
class SmellRepository
|
12
11
|
def self.smell_types
|
13
12
|
Reek::Smells::SmellDetector.descendants.sort_by(&:name)
|
14
13
|
end
|
15
14
|
|
16
|
-
def
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
@configuration = configuration
|
21
|
-
@smell_types = smell_types
|
22
|
-
|
23
|
-
configuration.directive_for(source_via).each do |klass, config|
|
24
|
-
configure klass, config
|
15
|
+
def self.eligible_smell_types(filter_by_smells = [])
|
16
|
+
return smell_types if filter_by_smells.empty?
|
17
|
+
smell_types.select do |klass|
|
18
|
+
filter_by_smells.include? klass.smell_type
|
25
19
|
end
|
26
20
|
end
|
27
21
|
|
28
|
-
def
|
29
|
-
|
30
|
-
|
31
|
-
|
22
|
+
def initialize(smell_types: self.class.smell_types,
|
23
|
+
configuration: {})
|
24
|
+
@configuration = configuration
|
25
|
+
@smell_types = smell_types
|
32
26
|
end
|
33
27
|
|
34
28
|
def report_on(listener)
|
35
29
|
detectors.each_value { |detector| detector.report_on(listener) }
|
36
30
|
end
|
37
31
|
|
38
|
-
def examine(
|
39
|
-
smell_listeners[
|
40
|
-
detector.examine(
|
32
|
+
def examine(context)
|
33
|
+
smell_listeners[context.type].each do |detector|
|
34
|
+
detector.examine(context)
|
41
35
|
end
|
42
36
|
end
|
43
37
|
|
44
38
|
def detectors
|
45
39
|
@initialized_detectors ||= smell_types.map do |klass|
|
46
|
-
{ klass => klass.new(
|
40
|
+
{ klass => klass.new(source_configuration_for(klass)) }
|
47
41
|
end.reduce({}, :merge)
|
48
42
|
end
|
49
43
|
|
50
44
|
private
|
51
45
|
|
52
|
-
private_attr_reader :configuration, :
|
46
|
+
private_attr_reader :configuration, :smell_types
|
47
|
+
|
48
|
+
def source_configuration_for(klass)
|
49
|
+
configuration[klass] || {}
|
50
|
+
end
|
53
51
|
|
52
|
+
# TODO: Make a method smell_detectors_for(scope)
|
54
53
|
def smell_listeners
|
55
54
|
@smell_listeners ||= Hash.new { |hash, key| hash[key] = [] }.tap do |listeners|
|
56
55
|
detectors.each_value { |detector| detector.register(listeners) }
|
@@ -1,53 +1,71 @@
|
|
1
1
|
require 'forwardable'
|
2
2
|
|
3
3
|
module Reek
|
4
|
+
# @public
|
4
5
|
module Smells
|
5
6
|
#
|
6
7
|
# Reports a warning that a smell has been found.
|
7
8
|
#
|
9
|
+
# @public
|
10
|
+
#
|
11
|
+
# :reek:TooManyInstanceVariables: { max_instance_variables: 6 }
|
8
12
|
class SmellWarning
|
9
13
|
include Comparable
|
10
14
|
extend Forwardable
|
11
|
-
attr_reader :context, :lines, :message, :parameters, :smell_detector
|
12
|
-
def_delegators :smell_detector, :smell_category, :smell_type, :source
|
13
15
|
|
16
|
+
# @public
|
17
|
+
attr_reader :context, :lines, :message, :parameters, :smell_detector, :source
|
18
|
+
def_delegators :smell_detector, :smell_category, :smell_type
|
19
|
+
|
20
|
+
# @note When using reek's public API, you should not create SmellWarning
|
21
|
+
# objects yourself. This is why the initializer is not part of the
|
22
|
+
# public API.
|
23
|
+
#
|
14
24
|
# FIXME: switch to required kwargs when dropping Ruby 2.0 compatibility
|
25
|
+
#
|
26
|
+
# :reek:LongParameterList: { max_params: 6 }
|
15
27
|
def initialize(smell_detector, context: '', lines: raise, message: raise,
|
16
|
-
parameters: {})
|
28
|
+
source: raise, parameters: {})
|
17
29
|
@smell_detector = smell_detector
|
30
|
+
@source = source
|
18
31
|
@context = context.to_s
|
19
32
|
@lines = lines
|
20
33
|
@message = message
|
21
34
|
@parameters = parameters
|
22
35
|
end
|
23
36
|
|
37
|
+
# @public
|
24
38
|
def hash
|
25
39
|
sort_key.hash
|
26
40
|
end
|
27
41
|
|
42
|
+
# @public
|
28
43
|
def <=>(other)
|
29
44
|
sort_key <=> other.sort_key
|
30
45
|
end
|
31
46
|
|
47
|
+
# @public
|
32
48
|
def eql?(other)
|
33
49
|
(self <=> other) == 0
|
34
50
|
end
|
35
51
|
|
36
|
-
# @api private
|
37
52
|
def matches?(klass, other_parameters = {})
|
38
53
|
smell_classes.include?(klass.to_s) && common_parameters_equal?(other_parameters)
|
39
54
|
end
|
40
55
|
|
41
|
-
# @api private
|
42
56
|
def report_on(listener)
|
43
57
|
listener.found_smell(self)
|
44
58
|
end
|
45
59
|
|
46
|
-
|
60
|
+
# @public
|
61
|
+
def yaml_hash
|
47
62
|
stringified_params = Hash[parameters.map { |key, val| [key.to_s, val] }]
|
48
63
|
core_yaml_hash.
|
49
|
-
merge(stringified_params)
|
50
|
-
|
64
|
+
merge(stringified_params)
|
65
|
+
end
|
66
|
+
|
67
|
+
def base_message
|
68
|
+
"#{context} #{message} (#{smell_type})"
|
51
69
|
end
|
52
70
|
|
53
71
|
protected
|
@@ -63,7 +81,10 @@ module Reek
|
|
63
81
|
end
|
64
82
|
|
65
83
|
def common_parameters_equal?(other_parameters)
|
66
|
-
other_parameters.keys
|
84
|
+
other_keys = other_parameters.keys
|
85
|
+
other_values = other_parameters.values
|
86
|
+
|
87
|
+
other_keys.each do |key|
|
67
88
|
unless parameters.key?(key)
|
68
89
|
raise ArgumentError, "The parameter #{key} you want to check for doesn't exist"
|
69
90
|
end
|
@@ -77,7 +98,7 @@ module Reek
|
|
77
98
|
# So in this spec we are just specifying the "name" parameter but not the "count".
|
78
99
|
# In order to allow for this kind of leniency we just test for common parameter equality,
|
79
100
|
# not for a strict one.
|
80
|
-
parameters.values_at(*
|
101
|
+
parameters.values_at(*other_keys) == other_values
|
81
102
|
end
|
82
103
|
|
83
104
|
def core_yaml_hash
|
@@ -85,19 +106,11 @@ module Reek
|
|
85
106
|
'context' => context,
|
86
107
|
'lines' => lines,
|
87
108
|
'message' => message,
|
88
|
-
'smell_category' =>
|
89
|
-
'smell_type' =>
|
90
|
-
'source' =>
|
109
|
+
'smell_category' => smell_category,
|
110
|
+
'smell_type' => smell_type,
|
111
|
+
'source' => source
|
91
112
|
}
|
92
113
|
end
|
93
|
-
|
94
|
-
def wiki_link_hash(warning_formatter)
|
95
|
-
if warning_formatter.respond_to?(:explanatory_link)
|
96
|
-
{ 'wiki_link' => warning_formatter.explanatory_link(smell_detector) }
|
97
|
-
else
|
98
|
-
{}
|
99
|
-
end
|
100
|
-
end
|
101
114
|
end
|
102
115
|
end
|
103
116
|
end
|
@@ -11,7 +11,6 @@ module Reek
|
|
11
11
|
# configurable number of instance variables.
|
12
12
|
#
|
13
13
|
# See {file:docs/Too-Many-Instance-Variables.md} for details.
|
14
|
-
# @api private
|
15
14
|
class TooManyInstanceVariables < SmellDetector
|
16
15
|
# The name of the config field that sets the maximum number of instance
|
17
16
|
# variables permitted in a class.
|
@@ -42,11 +41,11 @@ module Reek
|
|
42
41
|
max_allowed_ivars = value(MAX_ALLOWED_IVARS_KEY, ctx, DEFAULT_MAX_IVARS)
|
43
42
|
count = ctx.local_nodes(:ivasgn).map { |ivasgn| ivasgn[1] }.uniq.length
|
44
43
|
return [] if count <= max_allowed_ivars
|
45
|
-
[
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
44
|
+
[smell_warning(
|
45
|
+
context: ctx,
|
46
|
+
lines: [ctx.exp.line],
|
47
|
+
message: "has at least #{count} instance variables",
|
48
|
+
parameters: { count: count })]
|
50
49
|
end
|
51
50
|
end
|
52
51
|
end
|
@@ -13,7 +13,6 @@ module Reek
|
|
13
13
|
# modules.
|
14
14
|
#
|
15
15
|
# See {file:docs/Too-Many-Methods.md} for details.
|
16
|
-
# @api private
|
17
16
|
class TooManyMethods < SmellDetector
|
18
17
|
# The name of the config field that sets the maximum number of methods
|
19
18
|
# permitted in a class.
|
@@ -42,13 +41,14 @@ module Reek
|
|
42
41
|
#
|
43
42
|
def examine_context(ctx)
|
44
43
|
max_allowed_methods = value(MAX_ALLOWED_METHODS_KEY, ctx, DEFAULT_MAX_METHODS)
|
44
|
+
# TODO: Only checks instance methods!
|
45
45
|
actual = ctx.node_instance_methods.length
|
46
46
|
return [] if actual <= max_allowed_methods
|
47
|
-
[
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
47
|
+
[smell_warning(
|
48
|
+
context: ctx,
|
49
|
+
lines: [ctx.exp.line],
|
50
|
+
message: "has at least #{actual} methods",
|
51
|
+
parameters: { count: actual })]
|
52
52
|
end
|
53
53
|
end
|
54
54
|
end
|