reek 3.2 → 3.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -0
  3. data/lib/reek/ast/ast_node_class_map.rb +1 -5
  4. data/lib/reek/ast/node.rb +2 -4
  5. data/lib/reek/ast/object_refs.rb +5 -9
  6. data/lib/reek/ast/reference_collector.rb +2 -4
  7. data/lib/reek/cli/application.rb +9 -12
  8. data/lib/reek/cli/command.rb +0 -4
  9. data/lib/reek/cli/input.rb +4 -4
  10. data/lib/reek/cli/option_interpreter.rb +7 -11
  11. data/lib/reek/cli/options.rb +40 -42
  12. data/lib/reek/cli/reek_command.rb +3 -3
  13. data/lib/reek/cli/warning_collector.rb +3 -7
  14. data/lib/reek/code_comment.rb +1 -5
  15. data/lib/reek/context/code_context.rb +17 -19
  16. data/lib/reek/examiner.rb +6 -8
  17. data/lib/reek/rake/task.rb +22 -12
  18. data/lib/reek/report/formatter.rb +1 -5
  19. data/lib/reek/report/report.rb +13 -22
  20. data/lib/reek/smells/attribute.rb +6 -9
  21. data/lib/reek/smells/control_parameter.rb +13 -21
  22. data/lib/reek/smells/data_clump.rb +9 -17
  23. data/lib/reek/smells/duplicate_method_call.rb +6 -12
  24. data/lib/reek/smells/long_parameter_list.rb +2 -2
  25. data/lib/reek/smells/long_yield_list.rb +4 -4
  26. data/lib/reek/smells/nested_iterators.rb +2 -4
  27. data/lib/reek/smells/nil_check.rb +2 -6
  28. data/lib/reek/smells/repeated_conditional.rb +2 -2
  29. data/lib/reek/smells/smell_configuration.rb +7 -15
  30. data/lib/reek/smells/smell_detector.rb +10 -23
  31. data/lib/reek/smells/smell_warning.rb +6 -6
  32. data/lib/reek/smells/too_many_instance_variables.rb +2 -2
  33. data/lib/reek/smells/too_many_methods.rb +2 -2
  34. data/lib/reek/smells/too_many_statements.rb +4 -4
  35. data/lib/reek/smells/uncommunicative_method_name.rb +5 -5
  36. data/lib/reek/smells/uncommunicative_module_name.rb +5 -5
  37. data/lib/reek/smells/uncommunicative_parameter_name.rb +4 -8
  38. data/lib/reek/smells/uncommunicative_variable_name.rb +4 -8
  39. data/lib/reek/source/source_code.rb +1 -5
  40. data/lib/reek/spec/should_reek.rb +4 -9
  41. data/lib/reek/spec/should_reek_of.rb +5 -8
  42. data/lib/reek/spec/should_reek_only_of.rb +8 -12
  43. data/lib/reek/tree_dresser.rb +2 -6
  44. data/lib/reek/tree_walker.rb +22 -28
  45. data/lib/reek/version.rb +1 -1
  46. metadata +1 -1
@@ -52,9 +52,9 @@ module Reek
52
52
  # @return [Array<SmellWarning>]
53
53
  #
54
54
  def examine_context(ctx)
55
- max_copies = value(MAX_COPIES_KEY, ctx, DEFAULT_MAX_COPIES)
56
- min_clump_size = value(MIN_CLUMP_SIZE_KEY, ctx, DEFAULT_MIN_CLUMP_SIZE)
57
- MethodGroup.new(ctx, min_clump_size, max_copies).clumps.map do |clump, methods|
55
+ @max_copies = value(MAX_COPIES_KEY, ctx, DEFAULT_MAX_COPIES)
56
+ @min_clump_size = value(MIN_CLUMP_SIZE_KEY, ctx, DEFAULT_MIN_CLUMP_SIZE)
57
+ MethodGroup.new(ctx, @min_clump_size, @max_copies).clumps.map do |clump, methods|
58
58
  print_clump = DataClump.print_clump(clump)
59
59
  SmellWarning.new self,
60
60
  context: ctx.full_name,
@@ -88,10 +88,10 @@ module Reek
88
88
  end
89
89
 
90
90
  def candidate_clumps
91
- candidate_methods.each_cons(max_copies + 1).map do |methods|
91
+ @candidate_methods.each_cons(@max_copies + 1).map do |methods|
92
92
  common_argument_names_for(methods)
93
93
  end.select do |clump|
94
- clump.length >= min_clump_size
94
+ clump.length >= @min_clump_size
95
95
  end.uniq
96
96
  end
97
97
 
@@ -100,7 +100,7 @@ module Reek
100
100
  end
101
101
 
102
102
  def methods_containing_clump(clump)
103
- candidate_methods.select { |method| clump & method.arg_names == clump }
103
+ @candidate_methods.select { |method| clump & method.arg_names == clump }
104
104
  end
105
105
 
106
106
  def clumps
@@ -108,10 +108,6 @@ module Reek
108
108
  [clump, methods_containing_clump(clump)]
109
109
  end
110
110
  end
111
-
112
- private
113
-
114
- private_attr_reader :candidate_methods, :max_copies, :min_clump_size
115
111
  end
116
112
 
117
113
  # A method definition and a copy of its parameters
@@ -122,19 +118,15 @@ module Reek
122
118
  end
123
119
 
124
120
  def arg_names
125
- @arg_names ||= defn.arg_names.compact.sort
121
+ @arg_names ||= @defn.arg_names.compact.sort
126
122
  end
127
123
 
128
124
  def line
129
- defn.line
125
+ @defn.line
130
126
  end
131
127
 
132
128
  def name
133
- defn.name.to_s # BUG: should report the symbols!
129
+ @defn.name.to_s # BUG: should report the symbols!
134
130
  end
135
-
136
- private
137
-
138
- private_attr_reader :defn
139
131
  end
140
132
  end
@@ -68,24 +68,20 @@ module Reek
68
68
  end
69
69
 
70
70
  def record(occurence)
71
- occurences.push occurence
71
+ @occurences.push occurence
72
72
  end
73
73
 
74
74
  def call
75
- @call ||= call_node.format_to_ruby
75
+ @call ||= @call_node.format_to_ruby
76
76
  end
77
77
 
78
78
  def occurs
79
- occurences.length
79
+ @occurences.length
80
80
  end
81
81
 
82
82
  def lines
83
- occurences.map(&:line)
83
+ @occurences.map(&:line)
84
84
  end
85
-
86
- private
87
-
88
- private_attr_reader :call_node, :occurences
89
85
  end
90
86
 
91
87
  # Collects all calls in a given context
@@ -110,8 +106,6 @@ module Reek
110
106
 
111
107
  private
112
108
 
113
- private_attr_reader :allow_calls, :max_allowed_calls
114
-
115
109
  def collect_calls(result)
116
110
  context.each_node(:send, [:mlhs]) do |call_node|
117
111
  next if call_node.object_creation_call?
@@ -124,7 +118,7 @@ module Reek
124
118
  end
125
119
 
126
120
  def smelly_call?(found_call)
127
- found_call.occurs > max_allowed_calls && !allow_calls?(found_call.call)
121
+ found_call.occurs > @max_allowed_calls && !allow_calls?(found_call.call)
128
122
  end
129
123
 
130
124
  def simple_method_call?(call_node)
@@ -132,7 +126,7 @@ module Reek
132
126
  end
133
127
 
134
128
  def allow_calls?(method)
135
- allow_calls.any? { |allow| /#{allow}/ =~ method }
129
+ @allow_calls.any? { |allow| /#{allow}/ =~ method }
136
130
  end
137
131
  end
138
132
  end
@@ -35,9 +35,9 @@ module Reek
35
35
  # @return [Array<SmellWarning>]
36
36
  #
37
37
  def examine_context(ctx)
38
- max_allowed_params = value(MAX_ALLOWED_PARAMS_KEY, ctx, DEFAULT_MAX_ALLOWED_PARAMS)
38
+ @max_allowed_params = value(MAX_ALLOWED_PARAMS_KEY, ctx, DEFAULT_MAX_ALLOWED_PARAMS)
39
39
  count = ctx.exp.arg_names.length
40
- return [] if count <= max_allowed_params
40
+ return [] if count <= @max_allowed_params
41
41
  [SmellWarning.new(self,
42
42
  context: ctx.full_name,
43
43
  lines: [ctx.exp.line],
@@ -29,11 +29,11 @@ module Reek
29
29
  # @return [Array<SmellWarning>]
30
30
  #
31
31
  def examine_context(method_ctx)
32
- max_allowed_params = value(MAX_ALLOWED_PARAMS_KEY,
33
- method_ctx,
34
- DEFAULT_MAX_ALLOWED_PARAMS)
32
+ @max_allowed_params = value(MAX_ALLOWED_PARAMS_KEY,
33
+ method_ctx,
34
+ DEFAULT_MAX_ALLOWED_PARAMS)
35
35
  method_ctx.local_nodes(:yield).select do |yield_node|
36
- yield_node.args.length > max_allowed_params
36
+ yield_node.args.length > @max_allowed_params
37
37
  end.map do |yield_node|
38
38
  count = yield_node.args.length
39
39
  SmellWarning.new self,
@@ -50,10 +50,8 @@ module Reek
50
50
 
51
51
  private
52
52
 
53
- private_attr_accessor :ignore_iterators
54
-
55
53
  def find_deepest_iterator(ctx)
56
- self.ignore_iterators = value(IGNORE_ITERATORS_KEY, ctx, DEFAULT_IGNORE_ITERATORS)
54
+ @ignore_iterators = value(IGNORE_ITERATORS_KEY, ctx, DEFAULT_IGNORE_ITERATORS)
57
55
 
58
56
  find_iters(ctx.exp, 1).sort_by { |item| item[1] }.last
59
57
  end
@@ -75,7 +73,7 @@ module Reek
75
73
 
76
74
  def ignored_iterator?(exp)
77
75
  name = exp.call.method_name.to_s
78
- ignore_iterators.any? { |pattern| /#{pattern}/ =~ name }
76
+ @ignore_iterators.any? { |pattern| /#{pattern}/ =~ name }
79
77
  end
80
78
  end
81
79
  end
@@ -36,14 +36,10 @@ module Reek
36
36
  end
37
37
 
38
38
  def smelly_nodes
39
- nodes.select do |when_node|
40
- detector.detect(when_node)
39
+ @nodes.select do |when_node|
40
+ @detector.detect(when_node)
41
41
  end
42
42
  end
43
-
44
- private
45
-
46
- private_attr_reader :detector, :nodes
47
43
  end
48
44
 
49
45
  # Detect 'call' nodes which perform a nil check.
@@ -51,9 +51,9 @@ module Reek
51
51
  # @return [Array<SmellWarning>]
52
52
  #
53
53
  def examine_context(ctx)
54
- max_identical_ifs = value(MAX_IDENTICAL_IFS_KEY, ctx, DEFAULT_MAX_IFS)
54
+ @max_identical_ifs = value(MAX_IDENTICAL_IFS_KEY, ctx, DEFAULT_MAX_IFS)
55
55
  conditional_counts(ctx).select do |_key, lines|
56
- lines.length > max_identical_ifs
56
+ lines.length > @max_identical_ifs
57
57
  end.map do |key, lines|
58
58
  occurs = lines.length
59
59
  expression = key.format_to_ruby
@@ -17,8 +17,8 @@ module Reek
17
17
  @options = hash
18
18
  end
19
19
 
20
- def merge!(new_options)
21
- options.merge!(new_options)
20
+ def merge!(options)
21
+ @options.merge!(options)
22
22
  end
23
23
 
24
24
  #
@@ -26,11 +26,11 @@ module Reek
26
26
  #--
27
27
  # SMELL: Getter
28
28
  def enabled?
29
- options[ENABLED_KEY]
29
+ @options[ENABLED_KEY]
30
30
  end
31
31
 
32
32
  def overrides_for(context)
33
- Overrides.new(options.fetch(OVERRIDES_KEY, {})).for_context(context)
33
+ Overrides.new(@options.fetch(OVERRIDES_KEY, {})).for_context(context)
34
34
  end
35
35
 
36
36
  # Retrieves the value, if any, for the given +key+.
@@ -39,12 +39,8 @@ module Reek
39
39
  #
40
40
  def value(key, context, fall_back)
41
41
  overrides_for(context).each { |conf| return conf[key] if conf.key?(key) }
42
- options.fetch(key, fall_back)
42
+ @options.fetch(key, fall_back)
43
43
  end
44
-
45
- private
46
-
47
- private_attr_reader :options
48
44
  end
49
45
 
50
46
  #
@@ -58,13 +54,9 @@ module Reek
58
54
 
59
55
  # Find any overrides that match the supplied context
60
56
  def for_context(context)
61
- contexts = hash.keys.select { |ckey| context.matches?([ckey]) }
62
- contexts.map { |exc| hash[exc] }
57
+ contexts = @hash.keys.select { |ckey| context.matches?([ckey]) }
58
+ contexts.map { |exc| @hash[exc] }
63
59
  end
64
-
65
- private
66
-
67
- private_attr_reader :hash
68
60
  end
69
61
  end
70
62
  end
@@ -38,17 +38,12 @@ module Reek
38
38
  end
39
39
 
40
40
  def inherited(subclass)
41
- subclasses << subclass
41
+ @subclasses ||= []
42
+ @subclasses << subclass
42
43
  end
43
44
 
44
45
  def descendants
45
- subclasses
46
- end
47
-
48
- private
49
-
50
- def subclasses
51
- @subclasses ||= []
46
+ @subclasses
52
47
  end
53
48
  end
54
49
 
@@ -83,17 +78,17 @@ module Reek
83
78
  end
84
79
 
85
80
  def register(hooks)
86
- return unless config.enabled?
81
+ return unless @config.enabled?
87
82
  self.class.contexts.each { |ctx| hooks[ctx] << self }
88
83
  end
89
84
 
90
85
  # SMELL: Getter (only used in 1 test)
91
86
  def enabled?
92
- config.enabled?
87
+ @config.enabled?
93
88
  end
94
89
 
95
- def configure_with(new_config)
96
- config.merge!(new_config)
90
+ def configure_with(config)
91
+ @config.merge!(config)
97
92
  end
98
93
 
99
94
  def examine(context)
@@ -101,7 +96,7 @@ module Reek
101
96
  return if exception?(context)
102
97
 
103
98
  sm = examine_context(context)
104
- self.smells_found += sm
99
+ @smells_found += sm
105
100
  end
106
101
 
107
102
  def enabled_for?(context)
@@ -113,24 +108,16 @@ module Reek
113
108
  end
114
109
 
115
110
  def report_on(report)
116
- smells_found.each { |smell| smell.report_on(report) }
111
+ @smells_found.each { |smell| smell.report_on(report) }
117
112
  end
118
113
 
119
114
  def value(key, ctx, fall_back)
120
- config_for(ctx)[key] || config.value(key, ctx, fall_back)
115
+ config_for(ctx)[key] || @config.value(key, ctx, fall_back)
121
116
  end
122
117
 
123
118
  def config_for(ctx)
124
119
  ctx.config_for(self.class)
125
120
  end
126
-
127
- protected
128
-
129
- attr_writer :smells_found
130
-
131
- private
132
-
133
- private_attr_reader :config
134
121
  end
135
122
  end
136
123
  end
@@ -8,15 +8,15 @@ module Reek
8
8
  class SmellWarning
9
9
  include Comparable
10
10
  extend Forwardable
11
- attr_reader :context, :lines, :message, :parameters, :smell_detector
11
+ attr_accessor :smell_detector, :context, :lines, :message, :parameters
12
12
  def_delegators :smell_detector, :smell_category, :smell_type, :source
13
13
 
14
14
  def initialize(smell_detector, options = {})
15
- @smell_detector = smell_detector
16
- @context = options.fetch(:context, '').to_s
17
- @lines = options.fetch(:lines)
18
- @message = options.fetch(:message)
19
- @parameters = options.fetch(:parameters, {})
15
+ self.smell_detector = smell_detector
16
+ self.context = options.fetch(:context, '').to_s
17
+ self.lines = options.fetch(:lines)
18
+ self.message = options.fetch(:message)
19
+ self.parameters = options.fetch(:parameters, {})
20
20
  end
21
21
 
22
22
  def hash
@@ -39,9 +39,9 @@ module Reek
39
39
  # @return [Array<SmellWarning>]
40
40
  #
41
41
  def examine_context(ctx)
42
- max_allowed_ivars = value(MAX_ALLOWED_IVARS_KEY, ctx, DEFAULT_MAX_IVARS)
42
+ @max_allowed_ivars = value(MAX_ALLOWED_IVARS_KEY, ctx, DEFAULT_MAX_IVARS)
43
43
  count = ctx.local_nodes(:ivasgn).map { |ivasgn| ivasgn[1] }.uniq.length
44
- return [] if count <= max_allowed_ivars
44
+ return [] if count <= @max_allowed_ivars
45
45
  [SmellWarning.new(self,
46
46
  context: ctx.full_name,
47
47
  lines: [ctx.exp.line],
@@ -41,9 +41,9 @@ module Reek
41
41
  # @return [Array<SmellWarning>]
42
42
  #
43
43
  def examine_context(ctx)
44
- max_allowed_methods = value(MAX_ALLOWED_METHODS_KEY, ctx, DEFAULT_MAX_METHODS)
44
+ @max_allowed_methods = value(MAX_ALLOWED_METHODS_KEY, ctx, DEFAULT_MAX_METHODS)
45
45
  actual = ctx.node_instance_methods.length
46
- return [] if actual <= max_allowed_methods
46
+ return [] if actual <= @max_allowed_methods
47
47
  [SmellWarning.new(self,
48
48
  context: ctx.full_name,
49
49
  lines: [ctx.exp.line],
@@ -33,11 +33,11 @@ module Reek
33
33
  # @return [Array<SmellWarning>]
34
34
  #
35
35
  def examine_context(ctx)
36
- max_allowed_statements = value(MAX_ALLOWED_STATEMENTS_KEY,
37
- ctx,
38
- DEFAULT_MAX_STATEMENTS)
36
+ @max_allowed_statements = value(MAX_ALLOWED_STATEMENTS_KEY,
37
+ ctx,
38
+ DEFAULT_MAX_STATEMENTS)
39
39
  count = ctx.num_statements
40
- return [] if count <= max_allowed_statements
40
+ return [] if count <= @max_allowed_statements
41
41
  [SmellWarning.new(self,
42
42
  context: ctx.full_name,
43
43
  lines: [ctx.exp.line],
@@ -47,13 +47,13 @@ module Reek
47
47
  # @return [Array<SmellWarning>]
48
48
  #
49
49
  def examine_context(ctx)
50
- reject_names = value(REJECT_KEY, ctx, DEFAULT_REJECT_SET)
51
- accept_names = value(ACCEPT_KEY, ctx, DEFAULT_ACCEPT_SET)
50
+ @reject_names = value(REJECT_KEY, ctx, DEFAULT_REJECT_SET)
51
+ @accept_names = value(ACCEPT_KEY, ctx, DEFAULT_ACCEPT_SET)
52
52
  name = ctx.name.to_s
53
- return [] if accept_names.include?(ctx.full_name)
53
+ return [] if @accept_names.include?(ctx.full_name)
54
54
  var = name.gsub(/^[@\*\&]*/, '')
55
- return [] if accept_names.include?(var)
56
- return [] unless reject_names.find { |patt| patt =~ var }
55
+ return [] if @accept_names.include?(var)
56
+ return [] unless @reject_names.find { |patt| patt =~ var }
57
57
  [SmellWarning.new(self,
58
58
  context: ctx.full_name,
59
59
  lines: [ctx.exp.line],
@@ -52,15 +52,15 @@ module Reek
52
52
  #
53
53
  # :reek:Duplication { allow_calls: [ to_s ] }
54
54
  def examine_context(ctx)
55
- reject_names = value(REJECT_KEY, ctx, DEFAULT_REJECT_SET)
56
- accept_names = value(ACCEPT_KEY, ctx, DEFAULT_ACCEPT_SET)
55
+ @reject_names = value(REJECT_KEY, ctx, DEFAULT_REJECT_SET)
56
+ @accept_names = value(ACCEPT_KEY, ctx, DEFAULT_ACCEPT_SET)
57
57
  exp = ctx.exp
58
58
  full_name = ctx.full_name
59
59
  name = exp.simple_name.to_s
60
- return [] if accept_names.include?(full_name)
60
+ return [] if @accept_names.include?(full_name)
61
61
  var = name.gsub(/^[@\*\&]*/, '')
62
- return [] if accept_names.include?(var)
63
- return [] unless reject_names.find { |patt| patt =~ var }
62
+ return [] if @accept_names.include?(var)
63
+ return [] unless @reject_names.find { |patt| patt =~ var }
64
64
  [SmellWarning.new(self,
65
65
  context: full_name,
66
66
  lines: [exp.line],
@@ -47,8 +47,8 @@ module Reek
47
47
  # @return [Array<SmellWarning>]
48
48
  #
49
49
  def examine_context(ctx)
50
- self.reject_names = value(REJECT_KEY, ctx, DEFAULT_REJECT_SET)
51
- self.accept_names = value(ACCEPT_KEY, ctx, DEFAULT_ACCEPT_SET)
50
+ @reject_names = value(REJECT_KEY, ctx, DEFAULT_REJECT_SET)
51
+ @accept_names = value(ACCEPT_KEY, ctx, DEFAULT_ACCEPT_SET)
52
52
  context_expression = ctx.exp
53
53
  context_expression.parameter_names.select do |name|
54
54
  bad_name?(name) && ctx.uses_param?(name)
@@ -63,13 +63,9 @@ module Reek
63
63
 
64
64
  def bad_name?(name)
65
65
  var = name.to_s.gsub(/^[@\*\&]*/, '')
66
- return false if var == '*' || accept_names.include?(var)
67
- reject_names.find { |patt| patt =~ var }
66
+ return false if var == '*' || @accept_names.include?(var)
67
+ @reject_names.find { |patt| patt =~ var }
68
68
  end
69
-
70
- private
71
-
72
- private_attr_accessor :accept_names, :reject_names
73
69
  end
74
70
  end
75
71
  end