reek 3.2 → 3.2.1

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