rubocop 1.3.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/README.md +1 -1
- data/config/default.yml +75 -16
- data/lib/rubocop.rb +5 -0
- data/lib/rubocop/cli.rb +5 -1
- data/lib/rubocop/cli/command/execute_runner.rb +26 -11
- data/lib/rubocop/cli/command/suggest_extensions.rb +67 -0
- data/lib/rubocop/config_loader.rb +12 -4
- data/lib/rubocop/config_loader_resolver.rb +5 -1
- data/lib/rubocop/config_obsoletion.rb +21 -3
- data/lib/rubocop/config_regeneration.rb +1 -1
- data/lib/rubocop/config_validator.rb +8 -1
- data/lib/rubocop/cop/autocorrect_logic.rb +21 -6
- data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +1 -1
- data/lib/rubocop/cop/generator.rb +2 -9
- data/lib/rubocop/cop/generator/configuration_injector.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +1 -1
- data/lib/rubocop/cop/layout/class_structure.rb +15 -3
- data/lib/rubocop/cop/layout/empty_line_between_defs.rb +80 -10
- data/lib/rubocop/cop/layout/empty_lines_around_arguments.rb +6 -1
- data/lib/rubocop/cop/layout/end_of_line.rb +5 -5
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +7 -2
- data/lib/rubocop/cop/layout/space_around_method_call_operator.rb +1 -1
- data/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb +2 -1
- data/lib/rubocop/cop/lint/constant_definition_in_block.rb +4 -1
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +1 -1
- data/lib/rubocop/cop/lint/missing_super.rb +7 -4
- data/lib/rubocop/cop/lint/no_return_in_begin_end_blocks.rb +1 -1
- data/lib/rubocop/cop/lint/to_enum_arguments.rb +6 -15
- data/lib/rubocop/cop/lint/unexpected_block_arity.rb +85 -0
- data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +20 -6
- data/lib/rubocop/cop/metrics/abc_size.rb +25 -1
- data/lib/rubocop/cop/metrics/block_length.rb +13 -7
- data/lib/rubocop/cop/metrics/method_length.rb +7 -2
- data/lib/rubocop/cop/metrics/parameter_lists.rb +64 -1
- data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +20 -10
- data/lib/rubocop/cop/metrics/utils/repeated_attribute_discount.rb +146 -0
- data/lib/rubocop/cop/metrics/utils/repeated_csend_discount.rb +6 -1
- data/lib/rubocop/cop/mixin/configurable_numbering.rb +4 -3
- data/lib/rubocop/cop/mixin/enforce_superclass.rb +9 -1
- data/lib/rubocop/cop/mixin/ignored_methods.rb +36 -3
- data/lib/rubocop/cop/mixin/method_complexity.rb +6 -0
- data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +1 -1
- data/lib/rubocop/cop/mixin/visibility_help.rb +1 -3
- data/lib/rubocop/cop/style/and_or.rb +10 -0
- data/lib/rubocop/cop/style/class_and_module_children.rb +8 -3
- data/lib/rubocop/cop/style/document_dynamic_eval_definition.rb +8 -1
- data/lib/rubocop/cop/style/documentation.rb +12 -1
- data/lib/rubocop/cop/style/format_string.rb +8 -3
- data/lib/rubocop/cop/style/if_with_semicolon.rb +39 -4
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +2 -2
- data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +11 -2
- data/lib/rubocop/cop/style/negated_if_else_condition.rb +3 -1
- data/lib/rubocop/cop/style/numeric_literals.rb +14 -11
- data/lib/rubocop/cop/style/redundant_argument.rb +75 -0
- data/lib/rubocop/cop/style/redundant_condition.rb +2 -1
- data/lib/rubocop/cop/style/redundant_regexp_escape.rb +1 -1
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +49 -3
- data/lib/rubocop/cop/style/symbol_proc.rb +5 -3
- data/lib/rubocop/cop/util.rb +1 -1
- data/lib/rubocop/cop/variable_force/branch.rb +1 -1
- data/lib/rubocop/cop/variable_force/scope.rb +1 -1
- data/lib/rubocop/core_ext/hash.rb +20 -0
- data/lib/rubocop/ext/regexp_node.rb +5 -10
- data/lib/rubocop/ext/regexp_parser.rb +2 -9
- data/lib/rubocop/formatter/disabled_config_formatter.rb +21 -6
- data/lib/rubocop/options.rb +5 -0
- data/lib/rubocop/rake_task.rb +2 -2
- data/lib/rubocop/runner.rb +1 -1
- data/lib/rubocop/target_finder.rb +1 -1
- data/lib/rubocop/target_ruby.rb +12 -4
- data/lib/rubocop/version.rb +1 -1
- metadata +12 -10
- data/bin/console +0 -10
- data/bin/rubocop-profile +0 -32
- data/bin/setup +0 -7
@@ -13,6 +13,7 @@ module RuboCop
|
|
13
13
|
class AbcSizeCalculator
|
14
14
|
include IteratingBlock
|
15
15
|
include RepeatedCsendDiscount
|
16
|
+
prepend RepeatedAttributeDiscount
|
16
17
|
|
17
18
|
# > Branch -- an explicit forward program branch out of scope -- a
|
18
19
|
# > function call, class method call ..
|
@@ -24,8 +25,8 @@ module RuboCop
|
|
24
25
|
# > http://c2.com/cgi/wiki?AbcMetric
|
25
26
|
CONDITION_NODES = CyclomaticComplexity::COUNTED_NODES.freeze
|
26
27
|
|
27
|
-
def self.calculate(node)
|
28
|
-
new(node).calculate
|
28
|
+
def self.calculate(node, discount_repeated_attributes: false)
|
29
|
+
new(node, discount_repeated_attributes: discount_repeated_attributes).calculate
|
29
30
|
end
|
30
31
|
|
31
32
|
# TODO: move to rubocop-ast
|
@@ -42,14 +43,8 @@ module RuboCop
|
|
42
43
|
end
|
43
44
|
|
44
45
|
def calculate
|
45
|
-
@node
|
46
|
-
|
47
|
-
|
48
|
-
if branch?(child)
|
49
|
-
evaluate_branch_nodes(child)
|
50
|
-
elsif condition?(child)
|
51
|
-
evaluate_condition_node(child)
|
52
|
-
end
|
46
|
+
visit_depth_last(@node) do |child|
|
47
|
+
calculate_node(child)
|
53
48
|
end
|
54
49
|
|
55
50
|
[
|
@@ -80,6 +75,21 @@ module RuboCop
|
|
80
75
|
|
81
76
|
private
|
82
77
|
|
78
|
+
def visit_depth_last(node, &block)
|
79
|
+
node.each_child_node { |child| visit_depth_last(child, &block) }
|
80
|
+
yield node
|
81
|
+
end
|
82
|
+
|
83
|
+
def calculate_node(node)
|
84
|
+
@assignment += 1 if assignment?(node)
|
85
|
+
|
86
|
+
if branch?(node)
|
87
|
+
evaluate_branch_nodes(node)
|
88
|
+
elsif condition?(node)
|
89
|
+
evaluate_condition_node(node)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
83
93
|
def assignment?(node)
|
84
94
|
return compound_assignment(node) if node.masgn_type? || node.shorthand_asgn?
|
85
95
|
|
@@ -0,0 +1,146 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Metrics
|
6
|
+
module Utils
|
7
|
+
# @api private
|
8
|
+
#
|
9
|
+
# Identifies repetitions `{c}send` calls with no arguments:
|
10
|
+
#
|
11
|
+
# foo.bar
|
12
|
+
# foo.bar # => repeated
|
13
|
+
# foo.bar.baz.qux # => inner send repeated
|
14
|
+
# foo.bar.baz.other # => both inner send repeated
|
15
|
+
# foo.bar(2) # => not repeated
|
16
|
+
#
|
17
|
+
# It also invalidates sequences if a receiver is reassigned:
|
18
|
+
#
|
19
|
+
# xx.foo.bar
|
20
|
+
# xx.foo.baz # => inner send repeated
|
21
|
+
# self.xx = any # => invalidates everything so far
|
22
|
+
# xx.foo.baz # => no repetition
|
23
|
+
# self.xx.foo.baz # => all repeated
|
24
|
+
#
|
25
|
+
module RepeatedAttributeDiscount
|
26
|
+
extend NodePattern::Macros
|
27
|
+
include RuboCop::AST::Sexp
|
28
|
+
|
29
|
+
# Plug into the calculator
|
30
|
+
def initialize(node, discount_repeated_attributes: false)
|
31
|
+
super(node)
|
32
|
+
return unless discount_repeated_attributes
|
33
|
+
|
34
|
+
self_attributes = {} # Share hash for `(send nil? :foo)` and `(send (self) :foo)`
|
35
|
+
@known_attributes = {
|
36
|
+
s(:self) => self_attributes,
|
37
|
+
nil => self_attributes
|
38
|
+
}
|
39
|
+
# example after running `obj = foo.bar; obj.baz.qux`
|
40
|
+
# { nil => {foo: {bar: {}}},
|
41
|
+
# s(self) => same hash ^,
|
42
|
+
# s(:lvar, :obj) => {baz: {qux: {}}}
|
43
|
+
# }
|
44
|
+
end
|
45
|
+
|
46
|
+
def discount_repeated_attributes?
|
47
|
+
defined?(@known_attributes)
|
48
|
+
end
|
49
|
+
|
50
|
+
def evaluate_branch_nodes(node)
|
51
|
+
return if discount_repeated_attributes? && discount_repeated_attribute?(node)
|
52
|
+
|
53
|
+
super
|
54
|
+
end
|
55
|
+
|
56
|
+
def calculate_node(node)
|
57
|
+
update_repeated_attribute(node) if discount_repeated_attributes?
|
58
|
+
super
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
def_node_matcher :attribute_call?, <<~PATTERN
|
64
|
+
( {csend send} _receiver _method # and no parameters
|
65
|
+
)
|
66
|
+
PATTERN
|
67
|
+
|
68
|
+
def discount_repeated_attribute?(send_node)
|
69
|
+
return false unless attribute_call?(send_node)
|
70
|
+
|
71
|
+
repeated = true
|
72
|
+
find_attributes(send_node) do |hash, lookup|
|
73
|
+
return false if hash.nil?
|
74
|
+
|
75
|
+
repeated = false
|
76
|
+
hash[lookup] = {}
|
77
|
+
end
|
78
|
+
|
79
|
+
repeated
|
80
|
+
end
|
81
|
+
|
82
|
+
def update_repeated_attribute(node)
|
83
|
+
return unless (receiver, method = setter_to_getter(node))
|
84
|
+
|
85
|
+
calls = find_attributes(receiver) { return }
|
86
|
+
if method # e.g. `self.foo = 42`
|
87
|
+
calls.delete(method)
|
88
|
+
else # e.g. `var = 42`
|
89
|
+
calls.clear
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def_node_matcher :root_node?, <<~PATTERN
|
94
|
+
{ nil? | self # e.g. receiver of `my_method` or `self.my_attr`
|
95
|
+
| lvar | ivar | cvar | gvar # e.g. receiver of `var.my_method`
|
96
|
+
| const } # e.g. receiver of `MyConst.foo.bar`
|
97
|
+
PATTERN
|
98
|
+
|
99
|
+
# Returns the "known_attributes" for the `node` by walking the receiver tree
|
100
|
+
# If at any step the subdirectory does not exist, it is yielded with the
|
101
|
+
# associated key (method_name)
|
102
|
+
# If the node is not a series of `(c)send` calls with no arguments,
|
103
|
+
# then `nil` is yielded
|
104
|
+
def find_attributes(node, &block)
|
105
|
+
if attribute_call?(node)
|
106
|
+
calls = find_attributes(node.receiver, &block)
|
107
|
+
value = node.method_name
|
108
|
+
elsif root_node?(node)
|
109
|
+
calls = @known_attributes
|
110
|
+
value = node
|
111
|
+
else
|
112
|
+
return yield nil
|
113
|
+
end
|
114
|
+
|
115
|
+
calls.fetch(value) do
|
116
|
+
yield [calls, value]
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
VAR_SETTER_TO_GETTER = {
|
121
|
+
lvasgn: :lvar,
|
122
|
+
ivasgn: :ivar,
|
123
|
+
cvasgn: :cvar,
|
124
|
+
gvasgn: :gvar
|
125
|
+
}.freeze
|
126
|
+
|
127
|
+
# @returns `[receiver, method | nil]` for the given setter `node`
|
128
|
+
# or `nil` if it is not a setter.
|
129
|
+
def setter_to_getter(node)
|
130
|
+
if (type = VAR_SETTER_TO_GETTER[node.type])
|
131
|
+
# (lvasgn :my_var (int 42)) => [(lvar my_var), nil]
|
132
|
+
[s(type, node.children.first), nil]
|
133
|
+
elsif node.shorthand_asgn? # (or-asgn (send _receiver :foo) _value)
|
134
|
+
# (or-asgn (send _receiver :foo) _value) => [_receiver, :foo]
|
135
|
+
node.children.first.children
|
136
|
+
elsif node.respond_to?(:setter_method?) && node.setter_method?
|
137
|
+
# (send _receiver :foo= (int 42) ) => [_receiver, :foo]
|
138
|
+
method_name = node.method_name[0...-1].to_sym
|
139
|
+
[node.receiver, method_name]
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
@@ -6,7 +6,12 @@ module RuboCop
|
|
6
6
|
module Utils
|
7
7
|
# @api private
|
8
8
|
#
|
9
|
-
#
|
9
|
+
# Identifies repetitions `&.` on the same variable:
|
10
|
+
#
|
11
|
+
# my_var&.foo
|
12
|
+
# my_var&.bar # => repeated
|
13
|
+
# my_var = baz # => reset
|
14
|
+
# my_var&.qux # => not repeated
|
10
15
|
module RepeatedCsendDiscount
|
11
16
|
def reset_repeated_csend
|
12
17
|
@repeated_csend = {}
|
@@ -7,10 +7,11 @@ module RuboCop
|
|
7
7
|
module ConfigurableNumbering
|
8
8
|
include ConfigurableFormatting
|
9
9
|
|
10
|
+
implicit_param = /\A_\d+\z/
|
10
11
|
FORMATS = {
|
11
|
-
snake_case: /(?:\D|_\d+)
|
12
|
-
normalcase: /(?:\D|[^_\d]\d+)
|
13
|
-
non_integer:
|
12
|
+
snake_case: /(?:\D|_\d+|\A\d+)\z/,
|
13
|
+
normalcase: /(?:\D|[^_\d]\d+|\A\d+)\z|#{implicit_param}/,
|
14
|
+
non_integer: /(\D|\A\d+)\z|#{implicit_param}/
|
14
15
|
}.freeze
|
15
16
|
end
|
16
17
|
end
|
@@ -2,7 +2,15 @@
|
|
2
2
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
|
-
# Common functionality for enforcing a specific superclass
|
5
|
+
# Common functionality for enforcing a specific superclass.
|
6
|
+
#
|
7
|
+
# IMPORTANT: RuboCop core depended on this module when it supported Rails department.
|
8
|
+
# Rails department has been extracted to RuboCop Rails gem.
|
9
|
+
# This module is deprecated and will be removed by RuboCop 2.0.
|
10
|
+
# It will not be updated to `RuboCop::Cop::Base` v1 API to maintain compatibility
|
11
|
+
# with existing RuboCop Rails 2.8 or lower.
|
12
|
+
#
|
13
|
+
# @api private
|
6
14
|
module EnforceSuperclass
|
7
15
|
def self.included(base)
|
8
16
|
base.def_node_matcher :class_definition, <<~PATTERN
|
@@ -4,15 +4,48 @@ module RuboCop
|
|
4
4
|
module Cop
|
5
5
|
# This module encapsulates the ability to ignore certain methods when
|
6
6
|
# parsing.
|
7
|
+
# Cops that use `IgnoredMethods` can accept either strings or regexes to match
|
8
|
+
# against.
|
7
9
|
module IgnoredMethods
|
8
|
-
|
10
|
+
# Configuration for IgnoredMethods. It is added to classes that include
|
11
|
+
# the module so that configuration can be set using the `ignored_methods`
|
12
|
+
# class macro.
|
13
|
+
module Config
|
14
|
+
attr_accessor :deprecated_key
|
15
|
+
|
16
|
+
def ignored_methods(**config)
|
17
|
+
self.deprecated_key = config[:deprecated_key]
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.included(base)
|
22
|
+
base.extend(Config)
|
23
|
+
end
|
9
24
|
|
10
25
|
def ignored_method?(name)
|
11
|
-
ignored_methods.
|
26
|
+
ignored_methods.any? do |value|
|
27
|
+
case value
|
28
|
+
when Regexp
|
29
|
+
value.match? String(name)
|
30
|
+
else
|
31
|
+
value == String(name)
|
32
|
+
end
|
33
|
+
end
|
12
34
|
end
|
13
35
|
|
14
36
|
def ignored_methods
|
15
|
-
|
37
|
+
keys = %w[IgnoredMethods]
|
38
|
+
keys << deprecated_key if deprecated_key
|
39
|
+
|
40
|
+
cop_config.slice(*keys).values.reduce(&:concat)
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def deprecated_key
|
46
|
+
return unless self.class.respond_to?(:deprecated_key)
|
47
|
+
|
48
|
+
self.class.deprecated_key&.to_s
|
16
49
|
end
|
17
50
|
end
|
18
51
|
end
|
@@ -11,6 +11,12 @@ module RuboCop
|
|
11
11
|
include Metrics::Utils::RepeatedCsendDiscount
|
12
12
|
extend NodePattern::Macros
|
13
13
|
|
14
|
+
# Ensure cops that include `MethodComplexity` have the config
|
15
|
+
# `attr_accessor`s that `ignored_method?` needs.
|
16
|
+
def self.included(base)
|
17
|
+
base.extend(IgnoredMethods::Config)
|
18
|
+
end
|
19
|
+
|
14
20
|
def on_def(node)
|
15
21
|
return if ignored_method?(node.method_name)
|
16
22
|
|
@@ -31,7 +31,7 @@ module RuboCop
|
|
31
31
|
# b c { block }. <-- b is indented relative to a
|
32
32
|
# d <-- d is indented relative to a
|
33
33
|
def left_hand_side(lhs)
|
34
|
-
lhs = lhs.parent while lhs.parent&.send_type?
|
34
|
+
lhs = lhs.parent while lhs.parent&.send_type? && lhs.parent.loc.dot
|
35
35
|
lhs
|
36
36
|
end
|
37
37
|
|
@@ -16,9 +16,7 @@ module RuboCop
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def find_visibility_start(node)
|
19
|
-
node.left_siblings
|
20
|
-
.reverse
|
21
|
-
.find(&method(:visibility_block?))
|
19
|
+
node.left_siblings.reverse.find { |sibling| visibility_block?(sibling) }
|
22
20
|
end
|
23
21
|
|
24
22
|
# Navigate to find the last protected method
|
@@ -72,6 +72,8 @@ module RuboCop
|
|
72
72
|
end
|
73
73
|
|
74
74
|
corrector.replace(node.loc.operator, node.alternate_operator)
|
75
|
+
|
76
|
+
keep_operator_precedence(corrector, node)
|
75
77
|
end
|
76
78
|
end
|
77
79
|
|
@@ -123,6 +125,14 @@ module RuboCop
|
|
123
125
|
corrector.wrap(node, '(', ')')
|
124
126
|
end
|
125
127
|
|
128
|
+
def keep_operator_precedence(corrector, node)
|
129
|
+
if node.or_type? && node.parent&.and_type?
|
130
|
+
corrector.wrap(node, '(', ')')
|
131
|
+
elsif node.and_type? && node.rhs.or_type?
|
132
|
+
corrector.wrap(node.rhs, '(', ')')
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
126
136
|
def correctable_send?(node)
|
127
137
|
!node.parenthesized? && node.arguments? && !node.method?(:[])
|
128
138
|
end
|
@@ -55,13 +55,18 @@ module RuboCop
|
|
55
55
|
padding = ((' ' * indent_width) + leading_spaces(node)).to_s
|
56
56
|
padding_for_trailing_end = padding.sub(' ' * node.loc.end.column, '')
|
57
57
|
|
58
|
-
|
58
|
+
replace_namespace_keyword(corrector, node)
|
59
59
|
split_on_double_colon(corrector, node, padding)
|
60
60
|
add_trailing_end(corrector, node, padding_for_trailing_end)
|
61
61
|
end
|
62
62
|
|
63
|
-
def
|
64
|
-
|
63
|
+
def replace_namespace_keyword(corrector, node)
|
64
|
+
class_definition = node.left_sibling&.each_node(:class)&.find do |class_node|
|
65
|
+
class_node.identifier == node.identifier.namespace
|
66
|
+
end
|
67
|
+
namespace_keyword = class_definition ? 'class' : 'module'
|
68
|
+
|
69
|
+
corrector.replace(node.loc.keyword, namespace_keyword)
|
65
70
|
end
|
66
71
|
|
67
72
|
def split_on_double_colon(corrector, node, padding)
|
@@ -68,6 +68,12 @@ module RuboCop
|
|
68
68
|
# end
|
69
69
|
# EOT
|
70
70
|
# )
|
71
|
+
#
|
72
|
+
# # bad - interpolated string without comment
|
73
|
+
# class_eval("def #{unsafe_method}!(*params); end")
|
74
|
+
#
|
75
|
+
# # good - with inline comment or replace it with block comment using heredoc
|
76
|
+
# class_eval("def #{unsafe_method}!(*params); end # def capitalize!(*params); end")
|
71
77
|
class DocumentDynamicEvalDefinition < Base
|
72
78
|
BLOCK_COMMENT_REGEXP = /^\s*#(?!{)/.freeze
|
73
79
|
COMMENT_REGEXP = /\s*#(?!{).*/.freeze
|
@@ -79,7 +85,8 @@ module RuboCop
|
|
79
85
|
arg_node = node.first_argument
|
80
86
|
|
81
87
|
return unless arg_node&.dstr_type? && interpolated?(arg_node)
|
82
|
-
return if inline_comment_docs?(arg_node) ||
|
88
|
+
return if inline_comment_docs?(arg_node) ||
|
89
|
+
arg_node.heredoc? && comment_block_docs?(arg_node)
|
83
90
|
|
84
91
|
add_offense(node.loc.selector)
|
85
92
|
end
|
@@ -55,6 +55,11 @@ module RuboCop
|
|
55
55
|
# Public = Class.new
|
56
56
|
# end
|
57
57
|
#
|
58
|
+
# # Macro calls
|
59
|
+
# module Namespace
|
60
|
+
# extend Foo
|
61
|
+
# end
|
62
|
+
#
|
58
63
|
class Documentation < Base
|
59
64
|
include DocumentationComment
|
60
65
|
|
@@ -83,15 +88,21 @@ module RuboCop
|
|
83
88
|
return if documentation_comment?(node) || nodoc_comment?(node)
|
84
89
|
return if compact_namespace?(node) &&
|
85
90
|
nodoc_comment?(outer_module(node).first)
|
91
|
+
return if macro_only?(body)
|
86
92
|
|
87
93
|
add_offense(node.loc.keyword, message: format(MSG, type: type))
|
88
94
|
end
|
89
95
|
|
96
|
+
def macro_only?(body)
|
97
|
+
body.respond_to?(:macro?) && body.macro? ||
|
98
|
+
body.respond_to?(:children) && body.children&.all? { |child| macro_only?(child) }
|
99
|
+
end
|
100
|
+
|
90
101
|
def namespace?(node)
|
91
102
|
return false unless node
|
92
103
|
|
93
104
|
if node.begin_type?
|
94
|
-
node.children.all?
|
105
|
+
node.children.all? { |child| constant_declaration?(child) }
|
95
106
|
else
|
96
107
|
constant_definition?(node)
|
97
108
|
end
|
@@ -111,15 +111,20 @@ module RuboCop
|
|
111
111
|
format = format_arg.source
|
112
112
|
|
113
113
|
args = if param_args.one?
|
114
|
-
|
115
|
-
|
116
|
-
arg.hash_type? ? "{ #{arg.source} }" : arg.source
|
114
|
+
format_single_parameter(param_args.last)
|
117
115
|
else
|
118
116
|
"[#{param_args.map(&:source).join(', ')}]"
|
119
117
|
end
|
120
118
|
|
121
119
|
corrector.replace(node, "#{format} % #{args}")
|
122
120
|
end
|
121
|
+
|
122
|
+
def format_single_parameter(arg)
|
123
|
+
source = arg.source
|
124
|
+
return "{ #{source} }" if arg.hash_type?
|
125
|
+
|
126
|
+
arg.send_type? && arg.operator_method? && !arg.parenthesized? ? "(#{source})" : source
|
127
|
+
end
|
123
128
|
end
|
124
129
|
end
|
125
130
|
end
|