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.
- checksums.yaml +4 -4
- data/CHANGELOG +5 -0
- data/README.md +70 -92
- data/config/defaults.reek +3 -0
- data/features/samples.feature +24 -20
- data/features/step_definitions/reek_steps.rb +1 -1
- data/features/support/env.rb +7 -7
- data/lib/reek/core/code_context.rb +1 -1
- data/lib/reek/core/code_parser.rb +19 -18
- data/lib/reek/core/method_context.rb +8 -7
- data/lib/reek/core/module_context.rb +1 -1
- data/lib/reek/core/smell_repository.rb +1 -0
- data/lib/reek/core/sniffer.rb +3 -1
- data/lib/reek/rake/task.rb +1 -5
- data/lib/reek/smell_description.rb +26 -0
- data/lib/reek/smell_warning.rb +35 -49
- data/lib/reek/smells.rb +1 -0
- data/lib/reek/smells/attribute.rb +1 -1
- data/lib/reek/smells/control_parameter.rb +14 -7
- data/lib/reek/smells/data_clump.rb +1 -1
- data/lib/reek/smells/duplicate_method_call.rb +2 -9
- data/lib/reek/smells/module_initialize.rb +38 -0
- data/lib/reek/smells/nested_iterators.rb +1 -1
- data/lib/reek/smells/nil_check.rb +3 -3
- data/lib/reek/smells/repeated_conditional.rb +3 -2
- data/lib/reek/smells/smell_detector.rb +1 -1
- data/lib/reek/smells/too_many_instance_variables.rb +1 -1
- data/lib/reek/smells/too_many_methods.rb +1 -1
- data/lib/reek/smells/uncommunicative_method_name.rb +0 -4
- data/lib/reek/smells/uncommunicative_parameter_name.rb +0 -4
- data/lib/reek/smells/uncommunicative_variable_name.rb +11 -9
- data/lib/reek/smells/utility_function.rb +2 -2
- data/lib/reek/source/ast_node.rb +40 -0
- data/lib/reek/source/ast_node_class_map.rb +37 -0
- data/lib/reek/source/reference_collector.rb +3 -3
- data/lib/reek/source/sexp_extensions.rb +133 -59
- data/lib/reek/source/sexp_formatter.rb +10 -4
- data/lib/reek/source/sexp_node.rb +25 -17
- data/lib/reek/source/source_code.rb +21 -9
- data/lib/reek/source/tree_dresser.rb +10 -33
- data/lib/reek/version.rb +1 -1
- data/reek.gemspec +2 -4
- data/spec/matchers/smell_of_matcher.rb +9 -1
- data/spec/quality/reek_source_spec.rb +0 -35
- data/spec/reek/core/code_context_spec.rb +22 -8
- data/spec/reek/core/method_context_spec.rb +10 -10
- data/spec/reek/smell_description_spec.rb +43 -0
- data/spec/reek/smell_warning_spec.rb +0 -3
- data/spec/reek/smells/control_parameter_spec.rb +24 -0
- data/spec/reek/smells/feature_envy_spec.rb +50 -17
- data/spec/reek/smells/irresponsible_module_spec.rb +25 -17
- data/spec/reek/smells/module_initialize_spec.rb +20 -0
- data/spec/reek/smells/prima_donna_method_spec.rb +2 -2
- data/spec/reek/smells/repeated_conditional_spec.rb +10 -4
- data/spec/reek/smells/too_many_instance_variables_spec.rb +47 -21
- data/spec/reek/smells/too_many_statements_spec.rb +11 -1
- data/spec/reek/smells/uncommunicative_variable_name_spec.rb +1 -1
- data/spec/reek/smells/utility_function_spec.rb +26 -25
- data/spec/reek/source/sexp_extensions_spec.rb +164 -91
- data/spec/reek/source/sexp_formatter_spec.rb +13 -1
- data/spec/reek/source/sexp_node_spec.rb +5 -5
- data/spec/reek/source/source_code_spec.rb +18 -6
- data/spec/reek/source/tree_dresser_spec.rb +5 -5
- data/spec/spec_helper.rb +8 -4
- 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.
|
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.
|
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(:
|
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
|
@@ -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, :
|
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.
|
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?
|
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
|
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) }
|
@@ -45,7 +45,7 @@ module Reek
|
|
45
45
|
private
|
46
46
|
|
47
47
|
def check_num_ivars(ctx) # :nodoc:
|
48
|
-
count = ctx.local_nodes(:
|
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.
|
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",
|
@@ -42,7 +42,7 @@ module Reek
|
|
42
42
|
end
|
43
43
|
|
44
44
|
def self.contexts # :nodoc:
|
45
|
-
[:module, :class, :
|
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(:
|
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(:
|
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, :
|
93
|
+
when :defs, :def
|
94
94
|
exp.body
|
95
95
|
end
|
96
96
|
|
97
|
-
|
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
|
106
|
-
|
107
|
-
|
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
|
-
[:
|
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(:
|
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, :
|
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, :
|
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(:
|
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
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
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
|
-
|
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
|
-
|
26
|
+
false
|
27
|
+
end
|
28
|
+
|
29
|
+
def optional_argument?
|
30
|
+
false
|
19
31
|
end
|
20
32
|
|
21
33
|
def anonymous_splat?
|
22
|
-
|
34
|
+
false
|
23
35
|
end
|
36
|
+
end
|
24
37
|
|
25
|
-
|
26
|
-
|
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
|
-
|
30
|
-
|
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
|
-
|
35
|
-
|
61
|
+
# Utility methods for :blockarg nodes.
|
62
|
+
module BlockargNode
|
63
|
+
include ArgNodeBase
|
64
|
+
def block?
|
65
|
+
true
|
66
|
+
end
|
67
|
+
end
|
36
68
|
|
37
|
-
|
38
|
-
|
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 :
|
43
|
-
module
|
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
|
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
|
60
|
-
|
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
|
-
|
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 :
|
72
|
-
module
|
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
|
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
|
174
|
+
# Base module for utility methods for :def and :defs nodes.
|
175
|
+
module MethodNodeBase
|
98
176
|
def arguments
|
99
|
-
|
177
|
+
parameters.reject(&:block?)
|
100
178
|
end
|
101
179
|
|
102
180
|
def arg_names
|
103
|
-
|
181
|
+
arguments.map(&:name)
|
104
182
|
end
|
105
183
|
|
106
184
|
def parameters
|
107
|
-
|
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
|
-
|
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
|
-
|
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
|
215
|
+
self[3]
|
131
216
|
end
|
132
|
-
include
|
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
|
230
|
+
self[4]
|
146
231
|
end
|
147
|
-
|
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
|
159
|
-
|
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
|
-
|
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
|
-
|
186
|
-
|
187
|
-
self[2]
|
188
|
-
end
|
189
|
-
|
265
|
+
# Utility methods for :const nodes.
|
266
|
+
module ConstNode
|
190
267
|
def simple_name
|
191
|
-
|
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?(
|
277
|
+
name.is_a?(AST::Node) ? name.simple_name : name
|
204
278
|
end
|
205
279
|
|
206
280
|
def full_name(outer)
|