reek 1.4.0 → 1.5.0

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 (65) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +5 -0
  3. data/README.md +70 -92
  4. data/config/defaults.reek +3 -0
  5. data/features/samples.feature +24 -20
  6. data/features/step_definitions/reek_steps.rb +1 -1
  7. data/features/support/env.rb +7 -7
  8. data/lib/reek/core/code_context.rb +1 -1
  9. data/lib/reek/core/code_parser.rb +19 -18
  10. data/lib/reek/core/method_context.rb +8 -7
  11. data/lib/reek/core/module_context.rb +1 -1
  12. data/lib/reek/core/smell_repository.rb +1 -0
  13. data/lib/reek/core/sniffer.rb +3 -1
  14. data/lib/reek/rake/task.rb +1 -5
  15. data/lib/reek/smell_description.rb +26 -0
  16. data/lib/reek/smell_warning.rb +35 -49
  17. data/lib/reek/smells.rb +1 -0
  18. data/lib/reek/smells/attribute.rb +1 -1
  19. data/lib/reek/smells/control_parameter.rb +14 -7
  20. data/lib/reek/smells/data_clump.rb +1 -1
  21. data/lib/reek/smells/duplicate_method_call.rb +2 -9
  22. data/lib/reek/smells/module_initialize.rb +38 -0
  23. data/lib/reek/smells/nested_iterators.rb +1 -1
  24. data/lib/reek/smells/nil_check.rb +3 -3
  25. data/lib/reek/smells/repeated_conditional.rb +3 -2
  26. data/lib/reek/smells/smell_detector.rb +1 -1
  27. data/lib/reek/smells/too_many_instance_variables.rb +1 -1
  28. data/lib/reek/smells/too_many_methods.rb +1 -1
  29. data/lib/reek/smells/uncommunicative_method_name.rb +0 -4
  30. data/lib/reek/smells/uncommunicative_parameter_name.rb +0 -4
  31. data/lib/reek/smells/uncommunicative_variable_name.rb +11 -9
  32. data/lib/reek/smells/utility_function.rb +2 -2
  33. data/lib/reek/source/ast_node.rb +40 -0
  34. data/lib/reek/source/ast_node_class_map.rb +37 -0
  35. data/lib/reek/source/reference_collector.rb +3 -3
  36. data/lib/reek/source/sexp_extensions.rb +133 -59
  37. data/lib/reek/source/sexp_formatter.rb +10 -4
  38. data/lib/reek/source/sexp_node.rb +25 -17
  39. data/lib/reek/source/source_code.rb +21 -9
  40. data/lib/reek/source/tree_dresser.rb +10 -33
  41. data/lib/reek/version.rb +1 -1
  42. data/reek.gemspec +2 -4
  43. data/spec/matchers/smell_of_matcher.rb +9 -1
  44. data/spec/quality/reek_source_spec.rb +0 -35
  45. data/spec/reek/core/code_context_spec.rb +22 -8
  46. data/spec/reek/core/method_context_spec.rb +10 -10
  47. data/spec/reek/smell_description_spec.rb +43 -0
  48. data/spec/reek/smell_warning_spec.rb +0 -3
  49. data/spec/reek/smells/control_parameter_spec.rb +24 -0
  50. data/spec/reek/smells/feature_envy_spec.rb +50 -17
  51. data/spec/reek/smells/irresponsible_module_spec.rb +25 -17
  52. data/spec/reek/smells/module_initialize_spec.rb +20 -0
  53. data/spec/reek/smells/prima_donna_method_spec.rb +2 -2
  54. data/spec/reek/smells/repeated_conditional_spec.rb +10 -4
  55. data/spec/reek/smells/too_many_instance_variables_spec.rb +47 -21
  56. data/spec/reek/smells/too_many_statements_spec.rb +11 -1
  57. data/spec/reek/smells/uncommunicative_variable_name_spec.rb +1 -1
  58. data/spec/reek/smells/utility_function_spec.rb +26 -25
  59. data/spec/reek/source/sexp_extensions_spec.rb +164 -91
  60. data/spec/reek/source/sexp_formatter_spec.rb +13 -1
  61. data/spec/reek/source/sexp_node_spec.rb +5 -5
  62. data/spec/reek/source/source_code_spec.rb +18 -6
  63. data/spec/reek/source/tree_dresser_spec.rb +5 -5
  64. data/spec/spec_helper.rb +8 -4
  65. metadata +16 -50
@@ -85,7 +85,7 @@ module Reek
85
85
  def initialize(ctx, min_clump_size, max_copies)
86
86
  @min_clump_size = min_clump_size
87
87
  @max_copies = max_copies
88
- @candidate_methods = ctx.local_nodes(:defn).map do |defn_node|
88
+ @candidate_methods = ctx.node_instance_methods.map do |defn_node|
89
89
  CandidateMethod.new(defn_node)
90
90
  end
91
91
  end
@@ -102,7 +102,6 @@ module Reek
102
102
  def calls
103
103
  result = Hash.new { |hash, key| hash[key] = FoundCall.new(key) }
104
104
  collect_calls(result)
105
- collect_assignments(result)
106
105
  result.values.sort_by(&:call)
107
106
  end
108
107
 
@@ -112,19 +111,13 @@ module Reek
112
111
 
113
112
  private
114
113
 
115
- def collect_assignments(result)
116
- context.local_nodes(:attrasgn) do |asgn_node|
117
- result[asgn_node].record(asgn_node) if asgn_node.args
118
- end
119
- end
120
-
121
114
  def collect_calls(result)
122
- context.local_nodes(:call) do |call_node|
115
+ context.each_node(:send, [:mlhs]) do |call_node|
123
116
  next if call_node.method_name == :new
124
117
  next if !call_node.receiver && call_node.args.empty?
125
118
  result[call_node].record(call_node)
126
119
  end
127
- context.local_nodes(:iter) do |call_node|
120
+ context.local_nodes(:block) do |call_node|
128
121
  result[call_node].record(call_node)
129
122
  end
130
123
  end
@@ -0,0 +1,38 @@
1
+ require 'reek/smells/smell_detector'
2
+ require 'reek/smell_warning'
3
+
4
+ module Reek
5
+ module Smells
6
+ #
7
+ # a module is usually a mixin, so when initialize method is present it is
8
+ # hard to tell initialization order and parameters so having 'initialize'
9
+ # in a module is usually a bad idea
10
+ #
11
+ class ModuleInitialize < SmellDetector
12
+ SMELL_CLASS = smell_class_name
13
+ SMELL_SUBCLASS = SMELL_CLASS
14
+
15
+ def self.contexts # :nodoc:
16
+ [:module]
17
+ end
18
+
19
+ #
20
+ # Checks whether module has method 'initialize'.
21
+ #
22
+ # @return [Array<SmellWarning>]
23
+ #
24
+ def examine_context(module_ctx)
25
+ module_ctx.local_nodes(:def) do |node| # FIXME: also search for :defs?
26
+ if node.name.to_s == 'initialize'
27
+ return [
28
+ SmellWarning.new(SMELL_CLASS, module_ctx.full_name, [module_ctx.exp.line],
29
+ 'has initialize method',
30
+ @source, SMELL_SUBCLASS, {})
31
+ ]
32
+ end
33
+ end
34
+ []
35
+ end
36
+ end
37
+ end
38
+ end
@@ -62,7 +62,7 @@ module Reek
62
62
  end
63
63
 
64
64
  def find_iters(exp, depth)
65
- exp.unnested_nodes([:iter]).flat_map do |elem|
65
+ exp.find_nodes([:block]).flat_map do |elem|
66
66
  find_iters_for_iter_node(elem, depth)
67
67
  end
68
68
  end
@@ -10,7 +10,7 @@ module Reek
10
10
  SMELL_SUBCLASS = name.split(/::/)[-1]
11
11
 
12
12
  def examine_context(ctx)
13
- call_node_finder = NodeFinder.new(ctx, :call, NilCallNodeDetector)
13
+ call_node_finder = NodeFinder.new(ctx, :send, NilCallNodeDetector)
14
14
  case_node_finder = NodeFinder.new(ctx, :when, NilWhenNodeDetector)
15
15
  smelly_nodes = call_node_finder.smelly_nodes + case_node_finder.smelly_nodes
16
16
 
@@ -58,7 +58,7 @@ module Reek
58
58
  end
59
59
 
60
60
  def involves_nil?(call)
61
- call.receiver.nil_node? || call.args.any?(&:nil_node?)
61
+ call.participants.any? { |it| it.type == :nil }
62
62
  end
63
63
 
64
64
  def comparison_methods
@@ -71,7 +71,7 @@ module Reek
71
71
  module_function
72
72
 
73
73
  def detect(node)
74
- node.condition_list.any?(&:nil_node?)
74
+ node.condition_list.any? { |it| it.type == :nil }
75
75
  end
76
76
  end
77
77
  end
@@ -23,6 +23,7 @@ module Reek
23
23
  class RepeatedConditional < SmellDetector
24
24
  SMELL_CLASS = 'SimulatedPolymorphism'
25
25
  SMELL_SUBCLASS = name.split(/::/)[-1]
26
+ BLOCK_GIVEN_CONDITION = AST::Node.new(:send, [nil, :block_given?])
26
27
 
27
28
  def self.contexts # :nodoc:
28
29
  [:class]
@@ -65,8 +66,8 @@ module Reek
65
66
  def conditional_counts(sexp)
66
67
  result = Hash.new { |hash, key| hash[key] = [] }
67
68
  collector = proc do |node|
68
- condition = node.condition
69
- next if condition.nil? || condition == s(:call, nil, :block_given?)
69
+ next unless (condition = node.condition)
70
+ next if condition == BLOCK_GIVEN_CONDITION
70
71
  result[condition].push(condition.line)
71
72
  end
72
73
  [:if, :case].each { |stmt| sexp.local_nodes(stmt, &collector) }
@@ -25,7 +25,7 @@ module Reek
25
25
 
26
26
  class << self
27
27
  def contexts
28
- [:defn, :defs]
28
+ [:def, :defs]
29
29
  end
30
30
 
31
31
  def default_config
@@ -45,7 +45,7 @@ module Reek
45
45
  private
46
46
 
47
47
  def check_num_ivars(ctx) # :nodoc:
48
- count = ctx.local_nodes(:iasgn).map { |iasgn| iasgn[1] }.uniq.length
48
+ count = ctx.local_nodes(:ivasgn).map { |ivasgn| ivasgn[1] }.uniq.length
49
49
  return [] if count <= @max_allowed_ivars
50
50
  smell = SmellWarning.new(SMELL_CLASS, ctx.full_name, [ctx.exp.line],
51
51
  "has at least #{count} instance variables",
@@ -47,7 +47,7 @@ module Reek
47
47
  private
48
48
 
49
49
  def check_num_methods(ctx) # :nodoc:
50
- actual = ctx.local_nodes(:defn).length
50
+ actual = ctx.node_instance_methods.length
51
51
  return [] if actual <= @max_allowed_methods
52
52
  smell = SmellWarning.new(SMELL_CLASS, ctx.full_name, [ctx.exp.line],
53
53
  "has at least #{actual} methods",
@@ -41,10 +41,6 @@ module Reek
41
41
  )
42
42
  end
43
43
 
44
- def self.contexts # :nodoc:
45
- [:defn, :defs]
46
- end
47
-
48
44
  #
49
45
  # Checks the given +context+ for uncommunicative names.
50
46
  #
@@ -41,10 +41,6 @@ module Reek
41
41
  )
42
42
  end
43
43
 
44
- def self.contexts # :nodoc:
45
- [:defn, :defs]
46
- end
47
-
48
44
  #
49
45
  # Checks the given +context+ for uncommunicative names.
50
46
  #
@@ -42,7 +42,7 @@ module Reek
42
42
  end
43
43
 
44
44
  def self.contexts # :nodoc:
45
- [:module, :class, :defn, :defs]
45
+ [:module, :class, :def, :defs]
46
46
  end
47
47
 
48
48
  #
@@ -76,11 +76,11 @@ module Reek
76
76
  end
77
77
 
78
78
  def find_assignment_variable_names(exp, accumulator)
79
- assignment_nodes = exp.each_node(:lasgn, [:class, :module, :defs, :defn])
79
+ assignment_nodes = exp.each_node(:lvasgn, [:class, :module, :defs, :def])
80
80
 
81
81
  case exp.first
82
82
  when :class, :module
83
- assignment_nodes += exp.each_node(:iasgn, [:class, :module])
83
+ assignment_nodes += exp.each_node(:ivasgn, [:class, :module])
84
84
  end
85
85
 
86
86
  assignment_nodes.each { |asgn| accumulator[asgn[1]].push(asgn.line) }
@@ -90,11 +90,12 @@ module Reek
90
90
  arg_search_exp = case exp.first
91
91
  when :class, :module
92
92
  exp
93
- when :defs, :defn
93
+ when :defs, :def
94
94
  exp.body
95
95
  end
96
96
 
97
- args_nodes = arg_search_exp.each_node(:args, [:class, :module, :defs, :defn])
97
+ return unless arg_search_exp
98
+ args_nodes = arg_search_exp.each_node(:args, [:class, :module, :defs, :def])
98
99
 
99
100
  args_nodes.each do |args_node|
100
101
  recursively_record_variable_names(accumulator, args_node)
@@ -102,11 +103,12 @@ module Reek
102
103
  end
103
104
 
104
105
  def recursively_record_variable_names(accumulator, exp)
105
- exp[1..-1].each do |subexp|
106
- if subexp.is_a? Symbol
107
- record_variable_name(exp, subexp, accumulator)
108
- elsif subexp.first == :masgn
106
+ exp.children.each do |subexp|
107
+ case subexp.type
108
+ when :mlhs
109
109
  recursively_record_variable_names(accumulator, subexp)
110
+ else
111
+ record_variable_name(exp, subexp.name, accumulator)
110
112
  end
111
113
  end
112
114
  end
@@ -46,7 +46,7 @@ module Reek
46
46
 
47
47
  class << self
48
48
  def contexts # :nodoc:
49
- [:defn]
49
+ [:def]
50
50
  end
51
51
 
52
52
  def default_config
@@ -77,7 +77,7 @@ module Reek
77
77
  end
78
78
 
79
79
  def num_helper_methods(method_ctx)
80
- method_ctx.local_nodes(:call).length
80
+ method_ctx.local_nodes(:send).length
81
81
  end
82
82
  end
83
83
  end
@@ -0,0 +1,40 @@
1
+ require 'parser'
2
+
3
+ module Reek
4
+ module Source
5
+ # Base class for AST nodes extended with utility methods. Contains some
6
+ # methods to ease the transition from Sexp to AST::Node.
7
+ class AstNode < Parser::AST::Node
8
+ attr_reader :comments
9
+
10
+ def initialize(type, children = [], options = {})
11
+ @comments = options.fetch(:comments, [])
12
+ super
13
+ end
14
+
15
+ def comments
16
+ @comments.map(&:text).join("\n")
17
+ end
18
+
19
+ # @deprecated
20
+ def [](index)
21
+ elements[index]
22
+ end
23
+
24
+ def line
25
+ loc.line
26
+ end
27
+
28
+ # @deprecated
29
+ def first
30
+ type
31
+ end
32
+
33
+ private
34
+
35
+ def elements
36
+ [type, *children]
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,37 @@
1
+ require 'reek/source/ast_node'
2
+ require 'reek/source/sexp_node'
3
+ require 'reek/source/sexp_extensions'
4
+
5
+ module Reek
6
+ module Source
7
+ # Maps AST node types to sublasses of AstNode extended with the relevant
8
+ # utility modules.
9
+ class AstNodeClassMap
10
+ def initialize
11
+ @klass_map = {}
12
+ end
13
+
14
+ def klass_for(type)
15
+ @klass_map[type] ||=
16
+ begin
17
+ klass = Class.new(AstNode)
18
+ klass.send :include, extension_map[type] if extension_map[type]
19
+ klass.send :include, SexpNode
20
+ end
21
+ end
22
+
23
+ def extension_map
24
+ @extension_map ||=
25
+ begin
26
+ assoc = SexpExtensions.constants.map do |const|
27
+ [
28
+ const.to_s.sub(/Node$/, '').downcase.to_sym,
29
+ SexpExtensions.const_get(const)
30
+ ]
31
+ end
32
+ Hash[assoc]
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -6,7 +6,7 @@ module Reek
6
6
  # of an abstract syntax tree.
7
7
  #
8
8
  class ReferenceCollector
9
- STOP_NODES = [:class, :module, :defn, :defs]
9
+ STOP_NODES = [:class, :module, :def, :defs]
10
10
 
11
11
  def initialize(ast)
12
12
  @ast = ast
@@ -14,10 +14,10 @@ module Reek
14
14
 
15
15
  def num_refs_to_self
16
16
  result = 0
17
- [:self, :zsuper, :ivar, :iasgn].each do |node_type|
17
+ [:self, :zsuper, :ivar, :ivasgn].each do |node_type|
18
18
  @ast.look_for(node_type, STOP_NODES) { result += 1 }
19
19
  end
20
- @ast.look_for(:call, STOP_NODES) do |call|
20
+ @ast.look_for(:send, STOP_NODES) do |call|
21
21
  result += 1 unless call.receiver
22
22
  end
23
23
  result
@@ -3,51 +3,104 @@ require 'reek/source/sexp_node'
3
3
  module Reek
4
4
  module Source
5
5
  module SexpExtensions
6
- class MethodParameter
7
- attr_reader :name
8
-
9
- def initialize(name)
10
- @name = name
6
+ # Base module for utility methods for argument nodes.
7
+ module ArgNodeBase
8
+ def name
9
+ children.first
11
10
  end
12
11
 
12
+ # Other is a symbol?
13
13
  def ==(other)
14
- @name == other
14
+ name == other
15
+ end
16
+
17
+ def marked_unused?
18
+ plain_name.start_with?('_')
19
+ end
20
+
21
+ def plain_name
22
+ name.to_s
15
23
  end
16
24
 
17
25
  def block?
18
- @name.to_s =~ /^&/
26
+ false
27
+ end
28
+
29
+ def optional_argument?
30
+ false
19
31
  end
20
32
 
21
33
  def anonymous_splat?
22
- @name == :*
34
+ false
23
35
  end
36
+ end
24
37
 
25
- def marked_unused?
26
- plain_name.start_with?('_')
38
+ # Utility methods for :arg nodes.
39
+ module ArgNode
40
+ include ArgNodeBase
41
+ end
42
+
43
+ # Utility methods for :optarg nodes.
44
+ module OptargNode
45
+ include ArgNodeBase
46
+
47
+ def optional_argument?
48
+ true
27
49
  end
50
+ end
28
51
 
29
- def plain_name
30
- @plain_name ||= @name.to_s.sub(/^[*&]+/, '')
52
+ # Utility methods for :kwoptarg nodes.
53
+ module KwoptargNode
54
+ include ArgNodeBase
55
+
56
+ def optional_argument?
57
+ true
31
58
  end
32
59
  end
33
60
 
34
- module AndNode
35
- def condition() self[1] end
61
+ # Utility methods for :blockarg nodes.
62
+ module BlockargNode
63
+ include ArgNodeBase
64
+ def block?
65
+ true
66
+ end
67
+ end
36
68
 
37
- def body
38
- self[2]
69
+ # Utility methods for :restarg nodes.
70
+ module RestargNode
71
+ include ArgNodeBase
72
+ def anonymous_splat?
73
+ !name
39
74
  end
40
75
  end
41
76
 
42
- # Utility methods for :or nodes
43
- module OrNode
77
+ # Utility methods for :kwrestarg nodes.
78
+ module KwrestargNode
79
+ include ArgNodeBase
80
+ def anonymous_splat?
81
+ !name
82
+ end
83
+ end
84
+
85
+ # Base module for utility methods for :and and :or nodes.
86
+ module LogicOperatorBase
44
87
  def condition() self[1] end
45
88
 
46
- def body
47
- self[2]
89
+ def body_nodes(type, ignoring = [])
90
+ self[2].find_nodes type, ignoring
48
91
  end
49
92
  end
50
93
 
94
+ module AndNode
95
+ include LogicOperatorBase
96
+ end
97
+
98
+ # Utility methods for :or nodes
99
+ module OrNode
100
+ include LogicOperatorBase
101
+ end
102
+
103
+ # Utility methods for :attrasgn nodes
51
104
  module AttrasgnNode
52
105
  def args() self[3] end
53
106
  end
@@ -56,20 +109,28 @@ module Reek
56
109
  module CaseNode
57
110
  def condition() self[1] end
58
111
 
59
- def body
60
- self[2..-1].extend SexpNode
112
+ def body_nodes(type, ignoring = [])
113
+ children[1..-1].compact.flat_map { |child| child.find_nodes(type, ignoring) }
114
+ end
115
+
116
+ def else_body
117
+ children.last
61
118
  end
62
119
  end
63
120
 
64
121
  # Utility methods for :when nodes
65
122
  module WhenNode
66
123
  def condition_list
67
- self[1][1..-1]
124
+ children[0..-2]
125
+ end
126
+
127
+ def body
128
+ children.last
68
129
  end
69
130
  end
70
131
 
71
- # Utility methods for :call nodes
72
- module CallNode
132
+ # Utility methods for :send nodes
133
+ module SendNode
73
134
  def receiver() self[1] end
74
135
  def method_name() self[2] end
75
136
  def args() self[3..-1] end
@@ -83,34 +144,49 @@ module Reek
83
144
  end
84
145
  end
85
146
 
86
- module CvarNode
147
+ # Base module for utility methods for nodes representing variables.
148
+ module VariableBase
87
149
  def name() self[1] end
88
150
  end
89
151
 
152
+ # Utility methods for :cvar nodes.
153
+ module CvarNode
154
+ include VariableBase
155
+ end
156
+
90
157
  CvasgnNode = CvarNode
91
158
  CvdeclNode = CvarNode
92
159
 
160
+ # Utility methods for :ivar nodes.
161
+ module IvarNode
162
+ include VariableBase
163
+ end
164
+
165
+ # Utility methods for :ivasgn nodes.
166
+ module IvasgnNode
167
+ include VariableBase
168
+ end
169
+
93
170
  module LvarNode
94
171
  def var_name() self[1] end
95
172
  end
96
173
 
97
- module MethodNode
174
+ # Base module for utility methods for :def and :defs nodes.
175
+ module MethodNodeBase
98
176
  def arguments
99
- @arguments ||= parameters.reject(&:block?)
177
+ parameters.reject(&:block?)
100
178
  end
101
179
 
102
180
  def arg_names
103
- @arg_names ||= arguments.map(&:name)
181
+ arguments.map(&:name)
104
182
  end
105
183
 
106
184
  def parameters
107
- @parameters ||= argslist[1..-1].map do |param|
108
- MethodParameter.new(param.is_a?(Sexp) ? param[1] : param)
109
- end
185
+ argslist.children
110
186
  end
111
187
 
112
188
  def parameter_names
113
- @parameter_names ||= parameters.map(&:name)
189
+ parameters.map(&:name)
114
190
  end
115
191
 
116
192
  def name_without_bang
@@ -120,16 +196,25 @@ module Reek
120
196
  def ends_with_bang?
121
197
  name[-1] == '!'
122
198
  end
199
+
200
+ def body_nodes(types, ignoring = [])
201
+ if body
202
+ body.find_nodes(types, ignoring)
203
+ else
204
+ []
205
+ end
206
+ end
123
207
  end
124
208
 
125
- module DefnNode
209
+ # Utility methods for :def nodes.
210
+ module DefNode
126
211
  def name() self[1] end
127
212
  def argslist() self[2] end
128
213
 
129
214
  def body
130
- self[3..-1].extend SexpNode
215
+ self[3]
131
216
  end
132
- include MethodNode
217
+ include MethodNodeBase
133
218
  def full_name(outer)
134
219
  prefix = outer == '' ? '' : "#{outer}#"
135
220
  "#{prefix}#{name}"
@@ -142,9 +227,10 @@ module Reek
142
227
  def argslist() self[3] end
143
228
 
144
229
  def body
145
- self[4..-1].extend SexpNode
230
+ self[4]
146
231
  end
147
- include MethodNode
232
+
233
+ include MethodNodeBase
148
234
  def full_name(outer)
149
235
  prefix = outer == '' ? '' : "#{outer}#"
150
236
  "#{prefix}#{SexpNode.format(receiver)}.#{name}"
@@ -155,12 +241,13 @@ module Reek
155
241
  module IfNode
156
242
  def condition() self[1] end
157
243
 
158
- def body
159
- self[2..-1].extend SexpNode
244
+ def body_nodes(type, ignoring = [])
245
+ children[1..-1].compact.flat_map { |child| child.find_nodes(type, ignoring) }
160
246
  end
161
247
  end
162
248
 
163
- module IterNode
249
+ # Utility methods for :block nodes.
250
+ module BlockNode
164
251
  def call() self[1] end
165
252
  def args() self[2] end
166
253
  def block() self[3] end
@@ -171,36 +258,23 @@ module Reek
171
258
  end
172
259
  end
173
260
 
174
- # Utility methods for :nil nodes
175
- module NilNode
176
- def nil_node?
177
- true
178
- end
179
- end
180
-
181
261
  module LitNode
182
262
  def value() self[1] end
183
263
  end
184
264
 
185
- module Colon2Node
186
- def name
187
- self[2]
188
- end
189
-
265
+ # Utility methods for :const nodes.
266
+ module ConstNode
190
267
  def simple_name
191
- if name.is_a? Colon2Node
192
- name.simple_name
193
- else
194
- name
195
- end
268
+ children.last
196
269
  end
197
270
  end
198
271
 
272
+ # Utility methods for :module nodes.
199
273
  module ModuleNode
200
274
  def name() self[1] end
201
275
 
202
276
  def simple_name
203
- name.is_a?(Sexp) ? name.simple_name : name
277
+ name.is_a?(AST::Node) ? name.simple_name : name
204
278
  end
205
279
 
206
280
  def full_name(outer)