rubocop 1.1.0 → 1.4.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.
- checksums.yaml +4 -4
- data/README.md +29 -12
- data/config/default.yml +113 -16
- data/exe/rubocop +1 -1
- data/lib/rubocop.rb +9 -0
- data/lib/rubocop/cli/command/execute_runner.rb +26 -11
- data/lib/rubocop/config_loader.rb +14 -5
- data/lib/rubocop/config_regeneration.rb +1 -1
- data/lib/rubocop/cop/bundler/duplicated_gem.rb +3 -3
- data/lib/rubocop/cop/bundler/gem_comment.rb +1 -1
- data/lib/rubocop/cop/commissioner.rb +1 -1
- data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +1 -1
- data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +3 -3
- data/lib/rubocop/cop/gemspec/required_ruby_version.rb +4 -5
- data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.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/block_alignment.rb +3 -4
- data/lib/rubocop/cop/layout/class_structure.rb +15 -3
- data/lib/rubocop/cop/layout/else_alignment.rb +15 -2
- data/lib/rubocop/cop/layout/empty_line_between_defs.rb +77 -7
- data/lib/rubocop/cop/layout/end_alignment.rb +3 -3
- data/lib/rubocop/cop/layout/hash_alignment.rb +4 -4
- data/lib/rubocop/cop/layout/line_length.rb +8 -1
- data/lib/rubocop/cop/layout/space_around_block_parameters.rb +24 -18
- data/lib/rubocop/cop/layout/space_around_method_call_operator.rb +1 -1
- data/lib/rubocop/cop/layout/space_inside_parens.rb +35 -13
- data/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb +2 -1
- data/lib/rubocop/cop/lint/constant_definition_in_block.rb +26 -2
- data/lib/rubocop/cop/lint/debugger.rb +17 -27
- data/lib/rubocop/cop/lint/duplicate_branch.rb +93 -0
- data/lib/rubocop/cop/lint/duplicate_case_condition.rb +2 -12
- data/lib/rubocop/cop/lint/else_layout.rb +29 -3
- data/lib/rubocop/cop/lint/empty_block.rb +38 -2
- data/lib/rubocop/cop/lint/empty_class.rb +93 -0
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +22 -4
- data/lib/rubocop/cop/lint/loop.rb +4 -4
- data/lib/rubocop/cop/lint/missing_super.rb +7 -4
- data/lib/rubocop/cop/lint/nested_percent_literal.rb +14 -0
- data/lib/rubocop/cop/lint/no_return_in_begin_end_blocks.rb +58 -0
- data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +19 -16
- data/lib/rubocop/cop/lint/shadowed_exception.rb +4 -5
- data/lib/rubocop/cop/lint/to_enum_arguments.rb +6 -15
- data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +13 -4
- data/lib/rubocop/cop/lint/useless_method_definition.rb +2 -4
- data/lib/rubocop/cop/lint/useless_setter_call.rb +6 -1
- data/lib/rubocop/cop/metrics/method_length.rb +1 -1
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +1 -1
- data/lib/rubocop/cop/mixin/configurable_numbering.rb +3 -3
- data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +1 -1
- data/lib/rubocop/cop/mixin/statement_modifier.rb +9 -4
- data/lib/rubocop/cop/mixin/visibility_help.rb +1 -3
- data/lib/rubocop/cop/naming/binary_operator_parameter_name.rb +11 -1
- data/lib/rubocop/cop/naming/heredoc_delimiter_case.rb +11 -5
- data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +67 -18
- data/lib/rubocop/cop/naming/variable_number.rb +98 -8
- data/lib/rubocop/cop/style/and_or.rb +1 -3
- data/lib/rubocop/cop/style/bisected_attr_accessor.rb +0 -4
- data/lib/rubocop/cop/style/case_like_if.rb +0 -4
- data/lib/rubocop/cop/style/collection_compact.rb +91 -0
- data/lib/rubocop/cop/style/document_dynamic_eval_definition.rb +107 -5
- data/lib/rubocop/cop/style/documentation.rb +12 -1
- data/lib/rubocop/cop/style/double_negation.rb +6 -1
- data/lib/rubocop/cop/style/hash_syntax.rb +3 -3
- data/lib/rubocop/cop/style/identical_conditional_branches.rb +7 -2
- data/lib/rubocop/cop/style/if_inside_else.rb +37 -1
- data/lib/rubocop/cop/style/if_unless_modifier.rb +7 -3
- data/lib/rubocop/cop/style/infinite_loop.rb +4 -0
- data/lib/rubocop/cop/style/keyword_parameters_order.rb +12 -0
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +2 -2
- data/lib/rubocop/cop/style/mixin_grouping.rb +0 -4
- data/lib/rubocop/cop/style/multiple_comparison.rb +3 -2
- data/lib/rubocop/cop/style/negated_if_else_condition.rb +106 -0
- data/lib/rubocop/cop/style/nil_lambda.rb +52 -0
- data/lib/rubocop/cop/style/raise_args.rb +21 -6
- data/lib/rubocop/cop/style/redundant_argument.rb +73 -0
- data/lib/rubocop/cop/style/redundant_regexp_escape.rb +1 -1
- data/lib/rubocop/cop/style/static_class.rb +97 -0
- data/lib/rubocop/cop/style/while_until_modifier.rb +9 -0
- data/lib/rubocop/cop/util.rb +5 -1
- data/lib/rubocop/cop/variable_force/branch.rb +1 -1
- data/lib/rubocop/cop/variable_force/scope.rb +1 -1
- data/lib/rubocop/ext/regexp_node.rb +10 -5
- data/lib/rubocop/ext/regexp_parser.rb +9 -2
- data/lib/rubocop/formatter/disabled_config_formatter.rb +21 -6
- data/lib/rubocop/formatter/formatter_set.rb +1 -0
- data/lib/rubocop/formatter/git_hub_actions_formatter.rb +47 -0
- data/lib/rubocop/options.rb +7 -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 +65 -1
- data/lib/rubocop/version.rb +1 -1
- metadata +14 -8
- data/bin/console +0 -10
- data/bin/rubocop-profile +0 -32
- data/bin/setup +0 -7
@@ -7,42 +7,102 @@ module RuboCop
|
|
7
7
|
# configured style, snake_case, normalcase, or non_integer,
|
8
8
|
# for their numbering.
|
9
9
|
#
|
10
|
+
# Additionally, `CheckMethodNames` and `CheckSymbols` configuration options
|
11
|
+
# can be used to specify whether method names and symbols should be checked.
|
12
|
+
# Both are enabled by default.
|
13
|
+
#
|
10
14
|
# @example EnforcedStyle: snake_case
|
11
15
|
# # bad
|
12
|
-
#
|
16
|
+
# :some_sym1
|
13
17
|
# variable1 = 1
|
14
18
|
#
|
15
|
-
#
|
19
|
+
# def some_method1; end
|
16
20
|
#
|
21
|
+
# def some_method_1(arg1); end
|
22
|
+
#
|
23
|
+
# # good
|
24
|
+
# :some_sym_1
|
17
25
|
# variable_1 = 1
|
18
26
|
#
|
27
|
+
# def some_method_1; end
|
28
|
+
#
|
29
|
+
# def some_method_1(arg_1); end
|
30
|
+
#
|
19
31
|
# @example EnforcedStyle: normalcase (default)
|
20
32
|
# # bad
|
21
|
-
#
|
33
|
+
# :some_sym_1
|
22
34
|
# variable_1 = 1
|
23
35
|
#
|
24
|
-
#
|
36
|
+
# def some_method_1; end
|
25
37
|
#
|
38
|
+
# def some_method1(arg_1); end
|
39
|
+
#
|
40
|
+
# # good
|
41
|
+
# :some_sym1
|
26
42
|
# variable1 = 1
|
27
43
|
#
|
44
|
+
# def some_method1; end
|
45
|
+
#
|
46
|
+
# def some_method1(arg1); end
|
47
|
+
#
|
28
48
|
# @example EnforcedStyle: non_integer
|
29
49
|
# # bad
|
50
|
+
# :some_sym1
|
51
|
+
# :some_sym_1
|
30
52
|
#
|
31
53
|
# variable1 = 1
|
32
|
-
#
|
33
54
|
# variable_1 = 1
|
34
55
|
#
|
56
|
+
# def some_method1; end
|
57
|
+
#
|
58
|
+
# def some_method_1; end
|
59
|
+
#
|
60
|
+
# def some_methodone(arg1); end
|
61
|
+
# def some_methodone(arg_1); end
|
62
|
+
#
|
35
63
|
# # good
|
64
|
+
# :some_symone
|
65
|
+
# :some_sym_one
|
36
66
|
#
|
37
67
|
# variableone = 1
|
38
|
-
#
|
39
68
|
# variable_one = 1
|
69
|
+
#
|
70
|
+
# def some_methodone; end
|
71
|
+
#
|
72
|
+
# def some_method_one; end
|
73
|
+
#
|
74
|
+
# def some_methodone(argone); end
|
75
|
+
# def some_methodone(arg_one); end
|
76
|
+
#
|
77
|
+
# # In the following examples, we assume `EnforcedStyle: normalcase` (default).
|
78
|
+
#
|
79
|
+
# @example CheckMethodNames: true (default)
|
80
|
+
# # bad
|
81
|
+
# def some_method_1; end
|
82
|
+
#
|
83
|
+
# @example CheckMethodNames: false
|
84
|
+
# # good
|
85
|
+
# def some_method_1; end
|
86
|
+
#
|
87
|
+
# @example CheckSymbols: true (default)
|
88
|
+
# # bad
|
89
|
+
# :some_sym_1
|
90
|
+
#
|
91
|
+
# @example CheckSymbols: false
|
92
|
+
# # good
|
93
|
+
# :some_sym_1
|
94
|
+
#
|
95
|
+
# @example AllowedIdentifier: [capture3]
|
96
|
+
# # good
|
97
|
+
# expect(Open3).to receive(:capture3)
|
98
|
+
#
|
40
99
|
class VariableNumber < Base
|
41
100
|
include ConfigurableNumbering
|
42
101
|
|
43
|
-
MSG = 'Use %<style>s for
|
102
|
+
MSG = 'Use %<style>s for %<identifier_type>s numbers.'
|
44
103
|
|
45
104
|
def on_arg(node)
|
105
|
+
@node = node
|
46
106
|
name, = *node
|
47
107
|
check_name(node, name, node.loc.name)
|
48
108
|
end
|
@@ -50,10 +110,40 @@ module RuboCop
|
|
50
110
|
alias on_ivasgn on_arg
|
51
111
|
alias on_cvasgn on_arg
|
52
112
|
|
113
|
+
def on_def(node)
|
114
|
+
@node = node
|
115
|
+
return if allowed_identifier?(node.method_name)
|
116
|
+
|
117
|
+
check_name(node, node.method_name, node.loc.name) if cop_config['CheckMethodNames']
|
118
|
+
end
|
119
|
+
alias on_defs on_def
|
120
|
+
|
121
|
+
def on_sym(node)
|
122
|
+
@node = node
|
123
|
+
return if allowed_identifier?(node.value)
|
124
|
+
|
125
|
+
check_name(node, node.value, node) if cop_config['CheckSymbols']
|
126
|
+
end
|
127
|
+
|
53
128
|
private
|
54
129
|
|
55
130
|
def message(style)
|
56
|
-
|
131
|
+
identifier_type =
|
132
|
+
case @node.type
|
133
|
+
when :def, :defs then 'method name'
|
134
|
+
when :sym then 'symbol'
|
135
|
+
else 'variable'
|
136
|
+
end
|
137
|
+
|
138
|
+
format(MSG, style: style, identifier_type: identifier_type)
|
139
|
+
end
|
140
|
+
|
141
|
+
def allowed_identifier?(name)
|
142
|
+
allowed_identifiers.include?(name.to_s)
|
143
|
+
end
|
144
|
+
|
145
|
+
def allowed_identifiers
|
146
|
+
cop_config.fetch('AllowedIdentifiers', [])
|
57
147
|
end
|
58
148
|
end
|
59
149
|
end
|
@@ -66,9 +66,7 @@ module RuboCop
|
|
66
66
|
node.each_child_node do |expr|
|
67
67
|
if expr.send_type?
|
68
68
|
correct_send(expr, corrector)
|
69
|
-
elsif expr.return_type?
|
70
|
-
correct_other(expr, corrector)
|
71
|
-
elsif expr.assignment?
|
69
|
+
elsif expr.return_type? || expr.assignment?
|
72
70
|
correct_other(expr, corrector)
|
73
71
|
end
|
74
72
|
end
|
@@ -227,10 +227,6 @@ module RuboCop
|
|
227
227
|
range_between(node.parent.loc.keyword.begin_pos, node.loc.expression.end_pos)
|
228
228
|
end
|
229
229
|
|
230
|
-
def indent(node)
|
231
|
-
' ' * node.loc.column
|
232
|
-
end
|
233
|
-
|
234
230
|
# Named captures work with `=~` (if regexp is on lhs) and with `match` (both sides)
|
235
231
|
def regexp_with_working_captures?(node)
|
236
232
|
case node.type
|
@@ -0,0 +1,91 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# This cop checks for places where custom logic on rejection nils from arrays
|
7
|
+
# and hashes can be replaced with `{Array,Hash}#{compact,compact!}`.
|
8
|
+
#
|
9
|
+
# It is marked as unsafe by default because false positives may occur in the
|
10
|
+
# nil check of block arguments to the receiver object.
|
11
|
+
# For example, `[[1, 2], [3, nil]].reject { |first, second| second.nil? }`
|
12
|
+
# and `[[1, 2], [3, nil]].compact` are not compatible. This will work fine
|
13
|
+
# when the receiver is a hash object.
|
14
|
+
#
|
15
|
+
# @example
|
16
|
+
# # bad
|
17
|
+
# array.reject { |e| e.nil? }
|
18
|
+
# array.select { |e| !e.nil? }
|
19
|
+
#
|
20
|
+
# # good
|
21
|
+
# array.compact
|
22
|
+
#
|
23
|
+
# # bad
|
24
|
+
# hash.reject! { |k, v| v.nil? }
|
25
|
+
# hash.select! { |k, v| !v.nil? }
|
26
|
+
#
|
27
|
+
# # good
|
28
|
+
# hash.compact!
|
29
|
+
#
|
30
|
+
class CollectionCompact < Base
|
31
|
+
include RangeHelp
|
32
|
+
extend AutoCorrector
|
33
|
+
|
34
|
+
MSG = 'Use `%<good>s` instead of `%<bad>s`.'
|
35
|
+
|
36
|
+
RESTRICT_ON_SEND = %i[reject reject! select select!].freeze
|
37
|
+
|
38
|
+
def_node_matcher :reject_method?, <<~PATTERN
|
39
|
+
(block
|
40
|
+
(send
|
41
|
+
_ ${:reject :reject!})
|
42
|
+
$(args ...)
|
43
|
+
(send
|
44
|
+
$(lvar _) :nil?))
|
45
|
+
PATTERN
|
46
|
+
|
47
|
+
def_node_matcher :select_method?, <<~PATTERN
|
48
|
+
(block
|
49
|
+
(send
|
50
|
+
_ ${:select :select!})
|
51
|
+
$(args ...)
|
52
|
+
(send
|
53
|
+
(send
|
54
|
+
$(lvar _) :nil?) :!))
|
55
|
+
PATTERN
|
56
|
+
|
57
|
+
def on_send(node)
|
58
|
+
block_node = node.parent
|
59
|
+
return unless block_node&.block_type?
|
60
|
+
|
61
|
+
return unless (method_name, args, receiver =
|
62
|
+
reject_method?(block_node) || select_method?(block_node))
|
63
|
+
|
64
|
+
return unless args.last.source == receiver.source
|
65
|
+
|
66
|
+
range = offense_range(node, block_node)
|
67
|
+
good = good_method_name(method_name)
|
68
|
+
message = format(MSG, good: good, bad: range.source)
|
69
|
+
|
70
|
+
add_offense(range, message: message) do |corrector|
|
71
|
+
corrector.replace(range, good)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
|
77
|
+
def good_method_name(method_name)
|
78
|
+
if method_name.to_s.end_with?('!')
|
79
|
+
'compact!'
|
80
|
+
else
|
81
|
+
'compact'
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def offense_range(send_node, block_node)
|
86
|
+
range_between(send_node.loc.selector.begin_pos, block_node.loc.end.end_pos)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -25,7 +25,7 @@ module RuboCop
|
|
25
25
|
# end
|
26
26
|
# end
|
27
27
|
#
|
28
|
-
# # good
|
28
|
+
# # good, inline comments in heredoc
|
29
29
|
# UNSAFE_STRING_METHODS.each do |unsafe_method|
|
30
30
|
# if 'String'.respond_to?(unsafe_method)
|
31
31
|
# class_eval <<-EOT, __FILE__, __LINE__ + 1
|
@@ -41,25 +41,127 @@ module RuboCop
|
|
41
41
|
# end
|
42
42
|
# end
|
43
43
|
#
|
44
|
+
# # good, block comments in heredoc
|
45
|
+
# class_eval <<-EOT, __FILE__, __LINE__ + 1
|
46
|
+
# # def capitalize!(*params)
|
47
|
+
# # @dirty = true
|
48
|
+
# # super
|
49
|
+
# # end
|
50
|
+
#
|
51
|
+
# def #{unsafe_method}!(*params)
|
52
|
+
# @dirty = true
|
53
|
+
# super
|
54
|
+
# end
|
55
|
+
# EOT
|
56
|
+
#
|
57
|
+
# # good, block comments before heredoc
|
58
|
+
# class_eval(
|
59
|
+
# # def capitalize!(*params)
|
60
|
+
# # @dirty = true
|
61
|
+
# # super
|
62
|
+
# # end
|
63
|
+
#
|
64
|
+
# <<-EOT, __FILE__, __LINE__ + 1
|
65
|
+
# def #{unsafe_method}!(*params)
|
66
|
+
# @dirty = true
|
67
|
+
# super
|
68
|
+
# end
|
69
|
+
# EOT
|
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")
|
44
77
|
class DocumentDynamicEvalDefinition < Base
|
78
|
+
BLOCK_COMMENT_REGEXP = /^\s*#(?!{)/.freeze
|
79
|
+
COMMENT_REGEXP = /\s*#(?!{).*/.freeze
|
45
80
|
MSG = 'Add a comment block showing its appearance if interpolated.'
|
46
81
|
|
47
82
|
RESTRICT_ON_SEND = %i[eval class_eval module_eval instance_eval].freeze
|
48
83
|
|
49
84
|
def on_send(node)
|
50
85
|
arg_node = node.first_argument
|
51
|
-
return unless arg_node&.dstr_type?
|
52
86
|
|
53
|
-
|
87
|
+
return unless arg_node&.dstr_type? && interpolated?(arg_node)
|
88
|
+
return if inline_comment_docs?(arg_node) ||
|
89
|
+
arg_node.heredoc? && comment_block_docs?(arg_node)
|
90
|
+
|
91
|
+
add_offense(node.loc.selector)
|
54
92
|
end
|
55
93
|
|
56
94
|
private
|
57
95
|
|
58
|
-
def
|
96
|
+
def interpolated?(arg_node)
|
97
|
+
arg_node.each_child_node(:begin).any?
|
98
|
+
end
|
99
|
+
|
100
|
+
def inline_comment_docs?(node)
|
59
101
|
node.each_child_node(:begin).all? do |begin_node|
|
60
102
|
source_line = processed_source.lines[begin_node.first_line - 1]
|
61
|
-
source_line.match?(
|
103
|
+
source_line.match?(COMMENT_REGEXP)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def comment_block_docs?(arg_node)
|
108
|
+
comments = heredoc_comment_blocks(arg_node.loc.heredoc_body.line_span)
|
109
|
+
.concat(preceding_comment_blocks(arg_node.parent))
|
110
|
+
|
111
|
+
return if comments.none?
|
112
|
+
|
113
|
+
regexp = comment_regexp(arg_node)
|
114
|
+
comments.any? { |comment| regexp.match?(comment) } || regexp.match?(comments.join)
|
115
|
+
end
|
116
|
+
|
117
|
+
def preceding_comment_blocks(node)
|
118
|
+
# Collect comments in the method call, but outside the heredoc
|
119
|
+
comments = processed_source.each_comment_in_lines(node.loc.expression.line_span)
|
120
|
+
|
121
|
+
comments.each_with_object({}) do |comment, hash|
|
122
|
+
merge_adjacent_comments(comment.text, comment.loc.line, hash)
|
123
|
+
end.values
|
124
|
+
end
|
125
|
+
|
126
|
+
def heredoc_comment_blocks(heredoc_body)
|
127
|
+
# Collect comments inside the heredoc
|
128
|
+
line_range = (heredoc_body.begin - 1)..(heredoc_body.end - 1)
|
129
|
+
lines = processed_source.lines[line_range]
|
130
|
+
|
131
|
+
lines.each_with_object({}).with_index(line_range.begin) do |(line, hash), index|
|
132
|
+
merge_adjacent_comments(line, index, hash)
|
133
|
+
end.values
|
134
|
+
end
|
135
|
+
|
136
|
+
def merge_adjacent_comments(line, index, hash)
|
137
|
+
# Combine adjacent comment lines into a single string
|
138
|
+
return unless (line = line.dup.gsub!(BLOCK_COMMENT_REGEXP, ''))
|
139
|
+
|
140
|
+
hash[index] = if hash.keys.last == index - 1
|
141
|
+
[hash.delete(index - 1), line].join("\n")
|
142
|
+
else
|
143
|
+
line
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def comment_regexp(arg_node)
|
148
|
+
# Replace the interpolations with wildcards
|
149
|
+
regexp_parts = arg_node.child_nodes.map do |n|
|
150
|
+
n.begin_type? ? /.+/ : source_to_regexp(n.source)
|
62
151
|
end
|
152
|
+
|
153
|
+
Regexp.new(regexp_parts.join)
|
154
|
+
end
|
155
|
+
|
156
|
+
def source_to_regexp(source)
|
157
|
+
# Get the source in the heredoc being `eval`ed, without any comments
|
158
|
+
# and turn it into a regexp
|
159
|
+
return /\s+/ if source.blank?
|
160
|
+
|
161
|
+
source = source.gsub(COMMENT_REGEXP, '')
|
162
|
+
return if source.blank?
|
163
|
+
|
164
|
+
/\s*#{Regexp.escape(source.strip)}/
|
63
165
|
end
|
64
166
|
end
|
65
167
|
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
|