rubocop 1.32.0 → 1.37.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 +2 -2
- data/config/default.yml +104 -16
- data/config/obsoletion.yml +23 -1
- data/lib/rubocop/arguments_env.rb +17 -0
- data/lib/rubocop/arguments_file.rb +17 -0
- data/lib/rubocop/cache_config.rb +29 -0
- data/lib/rubocop/cli/command/{auto_genenerate_config.rb → auto_generate_config.rb} +2 -2
- data/lib/rubocop/cli/command/execute_runner.rb +7 -7
- data/lib/rubocop/cli/command/init_dotfile.rb +1 -1
- data/lib/rubocop/cli/command/suggest_extensions.rb +53 -15
- data/lib/rubocop/config.rb +1 -1
- data/lib/rubocop/config_finder.rb +68 -0
- data/lib/rubocop/config_loader.rb +12 -40
- data/lib/rubocop/config_loader_resolver.rb +1 -5
- data/lib/rubocop/config_obsoletion/changed_parameter.rb +5 -0
- data/lib/rubocop/config_obsoletion/parameter_rule.rb +4 -0
- data/lib/rubocop/config_obsoletion.rb +7 -2
- data/lib/rubocop/cop/cop.rb +1 -1
- data/lib/rubocop/cop/correctors/parentheses_corrector.rb +58 -0
- data/lib/rubocop/cop/gemspec/require_mfa.rb +1 -1
- data/lib/rubocop/cop/generator/require_file_injector.rb +2 -2
- data/lib/rubocop/cop/generator.rb +1 -2
- data/lib/rubocop/cop/internal_affairs/numblock_handler.rb +69 -0
- data/lib/rubocop/cop/internal_affairs/single_line_comparison.rb +62 -0
- data/lib/rubocop/cop/internal_affairs.rb +2 -0
- data/lib/rubocop/cop/layout/block_alignment.rb +16 -12
- data/lib/rubocop/cop/layout/block_end_newline.rb +35 -5
- data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +5 -2
- data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +2 -0
- data/lib/rubocop/cop/layout/end_of_line.rb +4 -4
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +7 -1
- data/lib/rubocop/cop/layout/first_array_element_indentation.rb +2 -2
- data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +2 -2
- data/lib/rubocop/cop/layout/indentation_width.rb +6 -2
- data/lib/rubocop/cop/layout/line_length.rb +4 -1
- data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +1 -1
- data/lib/rubocop/cop/layout/multiline_block_layout.rb +2 -0
- data/lib/rubocop/cop/layout/redundant_line_break.rb +1 -1
- data/lib/rubocop/cop/layout/space_around_block_parameters.rb +1 -1
- data/lib/rubocop/cop/layout/space_around_keyword.rb +1 -1
- data/lib/rubocop/cop/layout/space_before_block_braces.rb +2 -0
- data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +13 -9
- data/lib/rubocop/cop/layout/space_inside_block_braces.rb +25 -9
- data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +28 -3
- data/lib/rubocop/cop/legacy/corrections_proxy.rb +1 -1
- data/lib/rubocop/cop/legacy/corrector.rb +1 -1
- data/lib/rubocop/cop/lint/ambiguous_block_association.rb +21 -8
- data/lib/rubocop/cop/lint/debugger.rb +26 -16
- data/lib/rubocop/cop/lint/deprecated_class_methods.rb +4 -4
- data/lib/rubocop/cop/lint/duplicate_magic_comment.rb +73 -0
- data/lib/rubocop/cop/lint/duplicate_methods.rb +11 -1
- data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +25 -6
- data/lib/rubocop/cop/lint/duplicate_require.rb +1 -1
- data/lib/rubocop/cop/lint/empty_block.rb +1 -1
- data/lib/rubocop/cop/lint/empty_class.rb +3 -1
- data/lib/rubocop/cop/lint/empty_conditional_body.rb +107 -1
- data/lib/rubocop/cop/lint/erb_new_arguments.rb +9 -9
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +4 -0
- data/lib/rubocop/cop/lint/nested_method_definition.rb +50 -1
- data/lib/rubocop/cop/lint/next_without_accumulator.rb +25 -6
- data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +6 -6
- data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +12 -0
- data/lib/rubocop/cop/lint/number_conversion.rb +24 -8
- data/lib/rubocop/cop/lint/ordered_magic_comments.rb +4 -5
- data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +12 -1
- data/lib/rubocop/cop/lint/redundant_dir_glob_sort.rb +7 -0
- data/lib/rubocop/cop/lint/redundant_require_statement.rb +29 -9
- data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +9 -3
- data/lib/rubocop/cop/lint/redundant_with_index.rb +13 -10
- data/lib/rubocop/cop/lint/redundant_with_object.rb +12 -11
- data/lib/rubocop/cop/lint/require_parentheses.rb +1 -1
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +3 -2
- data/lib/rubocop/cop/lint/shadowed_exception.rb +15 -10
- data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +27 -3
- data/lib/rubocop/cop/lint/unreachable_loop.rb +9 -3
- data/lib/rubocop/cop/lint/unused_method_argument.rb +4 -0
- data/lib/rubocop/cop/lint/useless_access_modifier.rb +8 -6
- data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +1 -1
- data/lib/rubocop/cop/lint/void.rb +2 -0
- data/lib/rubocop/cop/metrics/abc_size.rb +3 -1
- data/lib/rubocop/cop/metrics/block_length.rb +6 -7
- data/lib/rubocop/cop/metrics/method_length.rb +8 -8
- data/lib/rubocop/cop/mixin/allowed_methods.rb +20 -1
- data/lib/rubocop/cop/mixin/allowed_pattern.rb +17 -1
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +1 -1
- data/lib/rubocop/cop/mixin/comments_help.rb +17 -1
- data/lib/rubocop/cop/mixin/enforce_superclass.rb +2 -1
- data/lib/rubocop/cop/mixin/frozen_string_literal.rb +4 -0
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +82 -4
- data/lib/rubocop/cop/mixin/hash_transform_method.rb +10 -6
- data/lib/rubocop/cop/mixin/method_complexity.rb +8 -13
- data/lib/rubocop/cop/mixin/multiline_element_indentation.rb +1 -1
- data/lib/rubocop/cop/mixin/range_help.rb +4 -5
- data/lib/rubocop/cop/mixin/rescue_node.rb +3 -1
- data/lib/rubocop/cop/mixin/surrounding_space.rb +6 -5
- data/lib/rubocop/cop/naming/block_parameter_name.rb +1 -1
- data/lib/rubocop/cop/naming/constant_name.rb +2 -2
- data/lib/rubocop/cop/naming/inclusive_language.rb +1 -1
- data/lib/rubocop/cop/naming/predicate_name.rb +24 -3
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +97 -1
- data/lib/rubocop/cop/style/accessor_grouping.rb +7 -3
- data/lib/rubocop/cop/style/arguments_forwarding.rb +2 -2
- data/lib/rubocop/cop/style/block_delimiters.rb +26 -7
- data/lib/rubocop/cop/style/case_equality.rb +40 -10
- data/lib/rubocop/cop/style/class_and_module_children.rb +4 -4
- data/lib/rubocop/cop/style/class_equality_comparison.rb +32 -7
- data/lib/rubocop/cop/style/class_methods_definitions.rb +2 -1
- data/lib/rubocop/cop/style/collection_compact.rb +6 -1
- data/lib/rubocop/cop/style/collection_methods.rb +2 -0
- data/lib/rubocop/cop/style/combinable_loops.rb +3 -1
- data/lib/rubocop/cop/style/double_negation.rb +2 -0
- data/lib/rubocop/cop/style/each_for_simple_loop.rb +41 -6
- data/lib/rubocop/cop/style/each_with_object.rb +39 -8
- data/lib/rubocop/cop/style/empty_block_parameter.rb +1 -1
- data/lib/rubocop/cop/style/empty_heredoc.rb +15 -1
- data/lib/rubocop/cop/style/empty_lambda_parameter.rb +1 -1
- data/lib/rubocop/cop/style/empty_method.rb +1 -1
- data/lib/rubocop/cop/style/endless_method.rb +1 -1
- data/lib/rubocop/cop/style/explicit_block_argument.rb +4 -0
- data/lib/rubocop/cop/style/for.rb +2 -0
- data/lib/rubocop/cop/style/format_string_token.rb +21 -8
- data/lib/rubocop/cop/style/guard_clause.rb +27 -16
- data/lib/rubocop/cop/style/hash_each_methods.rb +3 -1
- data/lib/rubocop/cop/style/hash_except.rb +0 -4
- data/lib/rubocop/cop/style/hash_syntax.rb +17 -0
- data/lib/rubocop/cop/style/if_unless_modifier.rb +1 -1
- data/lib/rubocop/cop/style/inverse_methods.rb +8 -6
- data/lib/rubocop/cop/style/magic_comment_format.rb +307 -0
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +15 -4
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +5 -1
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +7 -7
- data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +11 -6
- data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +4 -1
- data/lib/rubocop/cop/style/multiline_block_chain.rb +3 -1
- data/lib/rubocop/cop/style/multiline_in_pattern_then.rb +1 -1
- data/lib/rubocop/cop/style/negated_if_else_condition.rb +7 -1
- data/lib/rubocop/cop/style/next.rb +3 -5
- data/lib/rubocop/cop/style/nil_lambda.rb +1 -1
- data/lib/rubocop/cop/style/numeric_literals.rb +16 -1
- data/lib/rubocop/cop/style/numeric_predicate.rb +28 -8
- data/lib/rubocop/cop/style/object_then.rb +2 -0
- data/lib/rubocop/cop/style/operator_method_call.rb +39 -0
- data/lib/rubocop/cop/style/perl_backrefs.rb +22 -1
- data/lib/rubocop/cop/style/proc.rb +4 -1
- data/lib/rubocop/cop/style/redundant_begin.rb +3 -0
- data/lib/rubocop/cop/style/redundant_condition.rb +24 -6
- data/lib/rubocop/cop/style/redundant_fetch_block.rb +1 -1
- data/lib/rubocop/cop/style/redundant_initialize.rb +3 -1
- data/lib/rubocop/cop/style/redundant_parentheses.rb +19 -22
- data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +8 -1
- data/lib/rubocop/cop/style/redundant_self.rb +2 -0
- data/lib/rubocop/cop/style/redundant_sort.rb +21 -6
- data/lib/rubocop/cop/style/redundant_sort_by.rb +24 -8
- data/lib/rubocop/cop/style/redundant_string_escape.rb +173 -0
- data/lib/rubocop/cop/style/rescue_modifier.rb +1 -1
- data/lib/rubocop/cop/style/safe_navigation.rb +4 -2
- data/lib/rubocop/cop/style/single_line_block_params.rb +1 -1
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +14 -5
- data/lib/rubocop/cop/style/static_class.rb +32 -1
- data/lib/rubocop/cop/style/symbol_array.rb +3 -1
- data/lib/rubocop/cop/style/symbol_proc.rb +38 -12
- data/lib/rubocop/cop/style/ternary_parentheses.rb +1 -13
- data/lib/rubocop/cop/style/top_level_method_definition.rb +3 -1
- data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +1 -1
- data/lib/rubocop/cop/style/word_array.rb +3 -1
- data/lib/rubocop/cop/util.rb +1 -1
- data/lib/rubocop/ext/range.rb +15 -0
- data/lib/rubocop/feature_loader.rb +94 -0
- data/lib/rubocop/formatter/clang_style_formatter.rb +1 -1
- data/lib/rubocop/formatter/disabled_config_formatter.rb +9 -3
- data/lib/rubocop/formatter/html_formatter.rb +3 -3
- data/lib/rubocop/formatter/markdown_formatter.rb +1 -1
- data/lib/rubocop/formatter/tap_formatter.rb +1 -1
- data/lib/rubocop/options.rb +13 -13
- data/lib/rubocop/result_cache.rb +22 -20
- data/lib/rubocop/rspec/shared_contexts.rb +13 -1
- data/lib/rubocop/runner.rb +4 -0
- data/lib/rubocop/server/cache.rb +41 -2
- data/lib/rubocop/server/cli.rb +26 -2
- data/lib/rubocop/server/client_command/exec.rb +5 -0
- data/lib/rubocop/server/core.rb +2 -1
- data/lib/rubocop/server/socket_reader.rb +5 -1
- data/lib/rubocop/server.rb +1 -1
- data/lib/rubocop/version.rb +8 -2
- data/lib/rubocop.rb +8 -3
- metadata +20 -9
- data/lib/rubocop/cop/mixin/ignored_methods.rb +0 -52
@@ -0,0 +1,307 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# Ensures magic comments are written consistently throughout your code base.
|
7
|
+
# Looks for discrepancies in separators (`-` vs `_`) and capitalization for
|
8
|
+
# both magic comment directives and values.
|
9
|
+
#
|
10
|
+
# Required capitalization can be set with the `DirectiveCapitalization` and
|
11
|
+
# `ValueCapitalization` configuration keys.
|
12
|
+
#
|
13
|
+
# NOTE: If one of these configuration is set to nil, any capitalization is allowed.
|
14
|
+
#
|
15
|
+
# @example EnforcedStyle: snake_case (default)
|
16
|
+
# # The `snake_case` style will enforce that the frozen string literal
|
17
|
+
# # comment is written in snake case. (Words separated by underscores)
|
18
|
+
# # bad
|
19
|
+
# # frozen-string-literal: true
|
20
|
+
#
|
21
|
+
# module Bar
|
22
|
+
# # ...
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# # good
|
26
|
+
# # frozen_string_literal: false
|
27
|
+
#
|
28
|
+
# module Bar
|
29
|
+
# # ...
|
30
|
+
# end
|
31
|
+
#
|
32
|
+
# @example EnforcedStyle: kebab_case
|
33
|
+
# # The `kebab_case` style will enforce that the frozen string literal
|
34
|
+
# # comment is written in kebab case. (Words separated by hyphens)
|
35
|
+
# # bad
|
36
|
+
# # frozen_string_literal: true
|
37
|
+
#
|
38
|
+
# module Baz
|
39
|
+
# # ...
|
40
|
+
# end
|
41
|
+
#
|
42
|
+
# # good
|
43
|
+
# # frozen-string-literal: true
|
44
|
+
#
|
45
|
+
# module Baz
|
46
|
+
# # ...
|
47
|
+
# end
|
48
|
+
#
|
49
|
+
# @example DirectiveCapitalization: lowercase (default)
|
50
|
+
# # bad
|
51
|
+
# # FROZEN-STRING-LITERAL: true
|
52
|
+
#
|
53
|
+
# # good
|
54
|
+
# # frozen-string-literal: true
|
55
|
+
#
|
56
|
+
# @example DirectiveCapitalization: uppercase
|
57
|
+
# # bad
|
58
|
+
# # frozen-string-literal: true
|
59
|
+
#
|
60
|
+
# # good
|
61
|
+
# # FROZEN-STRING-LITERAL: true
|
62
|
+
#
|
63
|
+
# @example DirectiveCapitalization: nil
|
64
|
+
# # any capitalization is accepted
|
65
|
+
#
|
66
|
+
# # good
|
67
|
+
# # frozen-string-literal: true
|
68
|
+
#
|
69
|
+
# # good
|
70
|
+
# # FROZEN-STRING-LITERAL: true
|
71
|
+
#
|
72
|
+
# @example ValueCapitalization: nil (default)
|
73
|
+
# # any capitalization is accepted
|
74
|
+
#
|
75
|
+
# # good
|
76
|
+
# # frozen-string-literal: true
|
77
|
+
#
|
78
|
+
# # good
|
79
|
+
# # frozen-string-literal: TRUE
|
80
|
+
#
|
81
|
+
# @example ValueCapitalization: lowercase
|
82
|
+
# # when a value is not given, any capitalization is accepted
|
83
|
+
#
|
84
|
+
# # bad
|
85
|
+
# # frozen-string-literal: TRUE
|
86
|
+
#
|
87
|
+
# # good
|
88
|
+
# # frozen-string-literal: TRUE
|
89
|
+
#
|
90
|
+
# @example ValueCapitalization: uppercase
|
91
|
+
# # bad
|
92
|
+
# # frozen-string-literal: true
|
93
|
+
#
|
94
|
+
# # good
|
95
|
+
# # frozen-string-literal: TRUE
|
96
|
+
#
|
97
|
+
class MagicCommentFormat < Base
|
98
|
+
include ConfigurableEnforcedStyle
|
99
|
+
extend AutoCorrector
|
100
|
+
|
101
|
+
SNAKE_SEPARATOR = '_'
|
102
|
+
KEBAB_SEPARATOR = '-'
|
103
|
+
MSG = 'Prefer %<style>s case for magic comments.'
|
104
|
+
MSG_VALUE = 'Prefer %<case>s for magic comment values.'
|
105
|
+
|
106
|
+
# Value object to extract source ranges for the different parts of a magic comment
|
107
|
+
class CommentRange
|
108
|
+
extend Forwardable
|
109
|
+
|
110
|
+
DIRECTIVE_REGEXP = Regexp.union(MagicComment::KEYWORDS.map do |_, v|
|
111
|
+
Regexp.new(v, Regexp::IGNORECASE)
|
112
|
+
end).freeze
|
113
|
+
|
114
|
+
VALUE_REGEXP = Regexp.new("(?:#{DIRECTIVE_REGEXP}:\s*)(.*?)(?=;|$)")
|
115
|
+
|
116
|
+
def_delegators :@comment, :text, :loc
|
117
|
+
attr_reader :comment
|
118
|
+
|
119
|
+
def initialize(comment)
|
120
|
+
@comment = comment
|
121
|
+
end
|
122
|
+
|
123
|
+
# A magic comment can contain one directive (normal style) or
|
124
|
+
# multiple directives (emacs style)
|
125
|
+
def directives
|
126
|
+
@directives ||= begin
|
127
|
+
matches = []
|
128
|
+
|
129
|
+
text.scan(DIRECTIVE_REGEXP) do
|
130
|
+
offset = Regexp.last_match.offset(0)
|
131
|
+
matches << loc.expression.adjust(begin_pos: offset.first)
|
132
|
+
.with(end_pos: loc.expression.begin_pos + offset.last)
|
133
|
+
end
|
134
|
+
|
135
|
+
matches
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
# A magic comment can contain one value (normal style) or
|
140
|
+
# multiple directives (emacs style)
|
141
|
+
def values
|
142
|
+
@values ||= begin
|
143
|
+
matches = []
|
144
|
+
|
145
|
+
text.scan(VALUE_REGEXP) do
|
146
|
+
offset = Regexp.last_match.offset(1)
|
147
|
+
matches << loc.expression.adjust(begin_pos: offset.first)
|
148
|
+
.with(end_pos: loc.expression.begin_pos + offset.last)
|
149
|
+
end
|
150
|
+
|
151
|
+
matches
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def on_new_investigation
|
157
|
+
return unless processed_source.ast
|
158
|
+
|
159
|
+
magic_comments.each do |comment|
|
160
|
+
issues = find_issues(comment)
|
161
|
+
register_offenses(issues) if issues.any?
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
private
|
166
|
+
|
167
|
+
def magic_comments
|
168
|
+
processed_source.each_comment_in_lines(leading_comment_lines)
|
169
|
+
.select { |comment| MagicComment.parse(comment.text).valid? }
|
170
|
+
.map { |comment| CommentRange.new(comment) }
|
171
|
+
end
|
172
|
+
|
173
|
+
def leading_comment_lines
|
174
|
+
first_non_comment_token = processed_source.tokens.find { |token| !token.comment? }
|
175
|
+
|
176
|
+
if first_non_comment_token
|
177
|
+
0...first_non_comment_token.line
|
178
|
+
else
|
179
|
+
(0..)
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
def find_issues(comment)
|
184
|
+
issues = { directives: [], values: [] }
|
185
|
+
|
186
|
+
comment.directives.each do |directive|
|
187
|
+
issues[:directives] << directive if directive_offends?(directive)
|
188
|
+
end
|
189
|
+
|
190
|
+
comment.values.each do |value| # rubocop:disable Style/HashEachMethods
|
191
|
+
issues[:values] << value if wrong_capitalization?(value.source, value_capitalization)
|
192
|
+
end
|
193
|
+
|
194
|
+
issues
|
195
|
+
end
|
196
|
+
|
197
|
+
def directive_offends?(directive)
|
198
|
+
incorrect_separator?(directive.source) ||
|
199
|
+
wrong_capitalization?(directive.source, directive_capitalization)
|
200
|
+
end
|
201
|
+
|
202
|
+
def register_offenses(issues)
|
203
|
+
fix_directives(issues[:directives])
|
204
|
+
fix_values(issues[:values])
|
205
|
+
end
|
206
|
+
|
207
|
+
def fix_directives(issues)
|
208
|
+
return if issues.empty?
|
209
|
+
|
210
|
+
msg = format(MSG, style: expected_style)
|
211
|
+
|
212
|
+
issues.each do |directive|
|
213
|
+
add_offense(directive, message: msg) do |corrector|
|
214
|
+
replacement = replace_separator(replace_capitalization(directive.source,
|
215
|
+
directive_capitalization))
|
216
|
+
corrector.replace(directive, replacement)
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
def fix_values(issues)
|
222
|
+
return if issues.empty?
|
223
|
+
|
224
|
+
msg = format(MSG_VALUE, case: value_capitalization)
|
225
|
+
|
226
|
+
issues.each do |value|
|
227
|
+
add_offense(value, message: msg) do |corrector|
|
228
|
+
corrector.replace(value, replace_capitalization(value.source, value_capitalization))
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
def expected_style
|
234
|
+
[directive_capitalization, style].compact.join(' ').gsub(/_?case\b/, '')
|
235
|
+
end
|
236
|
+
|
237
|
+
def wrong_separator
|
238
|
+
style == :snake_case ? KEBAB_SEPARATOR : SNAKE_SEPARATOR
|
239
|
+
end
|
240
|
+
|
241
|
+
def correct_separator
|
242
|
+
style == :snake_case ? SNAKE_SEPARATOR : KEBAB_SEPARATOR
|
243
|
+
end
|
244
|
+
|
245
|
+
def incorrect_separator?(text)
|
246
|
+
text[wrong_separator]
|
247
|
+
end
|
248
|
+
|
249
|
+
def wrong_capitalization?(text, expected_case)
|
250
|
+
return false unless expected_case
|
251
|
+
|
252
|
+
case expected_case
|
253
|
+
when :lowercase
|
254
|
+
text != text.downcase
|
255
|
+
when :uppercase
|
256
|
+
text != text.upcase
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
def replace_separator(text)
|
261
|
+
text.tr(wrong_separator, correct_separator)
|
262
|
+
end
|
263
|
+
|
264
|
+
def replace_capitalization(text, style)
|
265
|
+
return text unless style
|
266
|
+
|
267
|
+
case style
|
268
|
+
when :lowercase
|
269
|
+
text.downcase
|
270
|
+
when :uppercase
|
271
|
+
text.upcase
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
def line_range(line)
|
276
|
+
processed_source.buffer.line_range(line)
|
277
|
+
end
|
278
|
+
|
279
|
+
def directive_capitalization
|
280
|
+
cop_config['DirectiveCapitalization']&.to_sym.tap do |style|
|
281
|
+
unless valid_capitalization?(style)
|
282
|
+
raise "Unknown `DirectiveCapitalization` #{style} selected!"
|
283
|
+
end
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
def value_capitalization
|
288
|
+
cop_config['ValueCapitalization']&.to_sym.tap do |style|
|
289
|
+
unless valid_capitalization?(style)
|
290
|
+
raise "Unknown `ValueCapitalization` #{style} selected!"
|
291
|
+
end
|
292
|
+
end
|
293
|
+
end
|
294
|
+
|
295
|
+
def valid_capitalization?(style)
|
296
|
+
return true unless style
|
297
|
+
|
298
|
+
supported_capitalizations.include?(style)
|
299
|
+
end
|
300
|
+
|
301
|
+
def supported_capitalizations
|
302
|
+
cop_config['SupportedCapitalizations'].map(&:to_sym)
|
303
|
+
end
|
304
|
+
end
|
305
|
+
end
|
306
|
+
end
|
307
|
+
end
|
@@ -20,8 +20,8 @@ module RuboCop
|
|
20
20
|
return if require_parentheses_for_hash_value_omission?(node)
|
21
21
|
return if syntax_like_method_call?(node)
|
22
22
|
return if super_call_without_arguments?(node)
|
23
|
-
return if allowed_camel_case_method_call?(node)
|
24
23
|
return if legitimate_call_with_parentheses?(node)
|
24
|
+
return if allowed_camel_case_method_call?(node)
|
25
25
|
return if allowed_string_interpolation_method_call?(node)
|
26
26
|
|
27
27
|
add_offense(offense_range(node), message: OMIT_MSG) do |corrector|
|
@@ -97,7 +97,8 @@ module RuboCop
|
|
97
97
|
call_in_optional_arguments?(node) ||
|
98
98
|
call_in_single_line_inheritance?(node) ||
|
99
99
|
allowed_multiline_call_with_parentheses?(node) ||
|
100
|
-
allowed_chained_call_with_parentheses?(node)
|
100
|
+
allowed_chained_call_with_parentheses?(node) ||
|
101
|
+
assignment_in_condition?(node)
|
101
102
|
end
|
102
103
|
|
103
104
|
def call_in_literals?(node)
|
@@ -130,7 +131,7 @@ module RuboCop
|
|
130
131
|
call_as_argument_or_chain?(node) ||
|
131
132
|
hash_literal_in_arguments?(node) ||
|
132
133
|
node.descendants.any? do |n|
|
133
|
-
n.forwarded_args_type? ||
|
134
|
+
n.forwarded_args_type? || ambiguous_literal?(n) || logical_operator?(n) ||
|
134
135
|
call_with_braced_block?(n)
|
135
136
|
end
|
136
137
|
end
|
@@ -166,7 +167,7 @@ module RuboCop
|
|
166
167
|
previous.parenthesized? || allowed_chained_call_with_parentheses?(previous)
|
167
168
|
end
|
168
169
|
|
169
|
-
def
|
170
|
+
def ambiguous_literal?(node)
|
170
171
|
splat?(node) || ternary_if?(node) || regexp_slash_literal?(node) || unary_literal?(node)
|
171
172
|
end
|
172
173
|
|
@@ -202,6 +203,16 @@ module RuboCop
|
|
202
203
|
def inside_string_interpolation?(node)
|
203
204
|
node.ancestors.drop_while { |a| !a.begin_type? }.any?(&:dstr_type?)
|
204
205
|
end
|
206
|
+
|
207
|
+
def assignment_in_condition?(node)
|
208
|
+
parent = node.parent
|
209
|
+
return false unless parent
|
210
|
+
|
211
|
+
grandparent = parent.parent
|
212
|
+
return false unless grandparent
|
213
|
+
|
214
|
+
parent.assignment? && (grandparent.conditional? || grandparent.when_type?)
|
215
|
+
end
|
205
216
|
end
|
206
217
|
# rubocop:enable Metrics/ModuleLength, Metrics/CyclomaticComplexity
|
207
218
|
end
|
@@ -12,7 +12,7 @@ module RuboCop
|
|
12
12
|
private
|
13
13
|
|
14
14
|
def require_parentheses(node)
|
15
|
-
return if
|
15
|
+
return if allowed_method_name?(node.method_name)
|
16
16
|
return if matches_allowed_pattern?(node.method_name)
|
17
17
|
return if eligible_for_parentheses_omission?(node)
|
18
18
|
return unless node.arguments? && !node.parenthesized?
|
@@ -24,6 +24,10 @@ module RuboCop
|
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
+
def allowed_method_name?(name)
|
28
|
+
allowed_method?(name) || matches_allowed_pattern?(name)
|
29
|
+
end
|
30
|
+
|
27
31
|
def eligible_for_parentheses_omission?(node)
|
28
32
|
node.operator_method? || node.setter_method? || ignored_macro?(node)
|
29
33
|
end
|
@@ -6,8 +6,8 @@ module RuboCop
|
|
6
6
|
# Enforces the presence (default) or absence of parentheses in
|
7
7
|
# method calls containing parameters.
|
8
8
|
#
|
9
|
-
# In the default style (require_parentheses), macro methods are
|
10
|
-
# Additional methods can be added to the `
|
9
|
+
# In the default style (require_parentheses), macro methods are allowed.
|
10
|
+
# Additional methods can be added to the `AllowedMethods`
|
11
11
|
# or `AllowedPatterns` list. These options are
|
12
12
|
# valid only in the default style. Macros can be included by
|
13
13
|
# either setting `IgnoreMacros` to false or adding specific macros to
|
@@ -15,13 +15,13 @@ module RuboCop
|
|
15
15
|
#
|
16
16
|
# Precedence of options is all follows:
|
17
17
|
#
|
18
|
-
# 1. `
|
18
|
+
# 1. `AllowedMethods`
|
19
19
|
# 2. `AllowedPatterns`
|
20
20
|
# 3. `IncludedMacros`
|
21
21
|
#
|
22
22
|
# eg. If a method is listed in both
|
23
|
-
# `IncludedMacros` and `
|
24
|
-
# precedence (that is, the method is
|
23
|
+
# `IncludedMacros` and `AllowedMethods`, then the latter takes
|
24
|
+
# precedence (that is, the method is allowed).
|
25
25
|
#
|
26
26
|
# In the alternative style (omit_parentheses), there are three additional
|
27
27
|
# options.
|
@@ -65,7 +65,7 @@ module RuboCop
|
|
65
65
|
# # Setter methods don't need parens
|
66
66
|
# foo.bar = baz
|
67
67
|
#
|
68
|
-
# # okay with `puts` listed in `
|
68
|
+
# # okay with `puts` listed in `AllowedMethods`
|
69
69
|
# puts 'test'
|
70
70
|
#
|
71
71
|
# # okay with `^assert` listed in `AllowedPatterns`
|
@@ -197,7 +197,7 @@ module RuboCop
|
|
197
197
|
require_relative 'method_call_with_args_parentheses/require_parentheses'
|
198
198
|
|
199
199
|
include ConfigurableEnforcedStyle
|
200
|
-
include
|
200
|
+
include AllowedMethods
|
201
201
|
include AllowedPattern
|
202
202
|
include RequireParentheses
|
203
203
|
include OmitParentheses
|
@@ -5,8 +5,8 @@ module RuboCop
|
|
5
5
|
module Style
|
6
6
|
# Checks for unwanted parentheses in parameterless method calls.
|
7
7
|
#
|
8
|
-
# This cop can be customized
|
9
|
-
# By default, there are no methods to
|
8
|
+
# This cop can be customized allowed methods with `AllowedMethods`.
|
9
|
+
# By default, there are no methods to allowed.
|
10
10
|
#
|
11
11
|
# @example
|
12
12
|
# # bad
|
@@ -15,16 +15,17 @@ module RuboCop
|
|
15
15
|
# # good
|
16
16
|
# object.some_method
|
17
17
|
#
|
18
|
-
# @example
|
18
|
+
# @example AllowedMethods: [] (default)
|
19
19
|
# # bad
|
20
20
|
# object.foo()
|
21
21
|
#
|
22
|
-
# @example
|
22
|
+
# @example AllowedMethods: [foo]
|
23
23
|
# # good
|
24
24
|
# object.foo()
|
25
25
|
#
|
26
26
|
class MethodCallWithoutArgsParentheses < Base
|
27
|
-
include
|
27
|
+
include AllowedMethods
|
28
|
+
include AllowedPattern
|
28
29
|
extend AutoCorrector
|
29
30
|
|
30
31
|
MSG = 'Do not use parentheses for method calls with no arguments.'
|
@@ -33,7 +34,7 @@ module RuboCop
|
|
33
34
|
return unless !node.arguments? && node.parenthesized?
|
34
35
|
return if ineligible_node?(node)
|
35
36
|
return if default_argument?(node)
|
36
|
-
return if
|
37
|
+
return if allowed_method_name?(node.method_name)
|
37
38
|
return if same_name_assignment?(node)
|
38
39
|
|
39
40
|
register_offense(node)
|
@@ -56,6 +57,10 @@ module RuboCop
|
|
56
57
|
node.parent&.optarg_type?
|
57
58
|
end
|
58
59
|
|
60
|
+
def allowed_method_name?(name)
|
61
|
+
allowed_method?(name) || matches_allowed_pattern?(name)
|
62
|
+
end
|
63
|
+
|
59
64
|
def same_name_assignment?(node)
|
60
65
|
any_assignment?(node) do |asgn_node|
|
61
66
|
next variable_in_mass_assignment?(node.method_name, asgn_node) if asgn_node.masgn_type?
|
@@ -35,12 +35,15 @@ module RuboCop
|
|
35
35
|
ignore_node(node.send_node)
|
36
36
|
end
|
37
37
|
|
38
|
+
alias on_numblock on_block
|
39
|
+
|
38
40
|
def on_send(node)
|
39
41
|
return if ignored_node?(node)
|
40
42
|
|
41
43
|
receiver = node.receiver
|
42
44
|
|
43
|
-
return unless receiver&.block_type?
|
45
|
+
return unless (receiver&.block_type? || receiver&.numblock_type?) &&
|
46
|
+
receiver.loc.end.is?('end')
|
44
47
|
|
45
48
|
range = range_between(receiver.loc.end.begin_pos, node.source_range.end_pos)
|
46
49
|
|
@@ -31,7 +31,7 @@ module RuboCop
|
|
31
31
|
node.send_node.each_node(:send) do |send_node|
|
32
32
|
receiver = send_node.receiver
|
33
33
|
|
34
|
-
next unless receiver&.block_type? && receiver&.multiline?
|
34
|
+
next unless (receiver&.block_type? || receiver&.numblock_type?) && receiver&.multiline?
|
35
35
|
|
36
36
|
range = range_between(receiver.loc.end.begin_pos, node.send_node.source_range.end_pos)
|
37
37
|
|
@@ -42,6 +42,8 @@ module RuboCop
|
|
42
42
|
break
|
43
43
|
end
|
44
44
|
end
|
45
|
+
|
46
|
+
alias on_numblock on_block
|
45
47
|
end
|
46
48
|
end
|
47
49
|
end
|
@@ -49,7 +49,7 @@ module RuboCop
|
|
49
49
|
|
50
50
|
# Requires `then` for write `in` and its body on the same line.
|
51
51
|
def require_then?(in_pattern_node)
|
52
|
-
return true
|
52
|
+
return true unless in_pattern_node.pattern.single_line?
|
53
53
|
return false unless in_pattern_node.body
|
54
54
|
|
55
55
|
same_line?(in_pattern_node, in_pattern_node.body)
|
@@ -49,7 +49,8 @@ module RuboCop
|
|
49
49
|
def on_if(node)
|
50
50
|
return unless if_else?(node)
|
51
51
|
|
52
|
-
condition = node.condition
|
52
|
+
condition = unwrap_begin_nodes(node.condition)
|
53
|
+
|
53
54
|
return if double_negation?(condition) || !negated_condition?(condition)
|
54
55
|
|
55
56
|
type = node.ternary? ? 'ternary' : 'if-else'
|
@@ -71,6 +72,11 @@ module RuboCop
|
|
71
72
|
!node.elsif? && else_branch && (!else_branch.if_type? || !else_branch.elsif?)
|
72
73
|
end
|
73
74
|
|
75
|
+
def unwrap_begin_nodes(node)
|
76
|
+
node = node.children.first while node.begin_type? || node.kwbegin_type?
|
77
|
+
node
|
78
|
+
end
|
79
|
+
|
74
80
|
def negated_condition?(node)
|
75
81
|
node.send_type? &&
|
76
82
|
(node.negation_method? || NEGATED_EQUALITY_METHODS.include?(node.method_name))
|
@@ -71,6 +71,8 @@ module RuboCop
|
|
71
71
|
check(node)
|
72
72
|
end
|
73
73
|
|
74
|
+
alias on_numblock on_block
|
75
|
+
|
74
76
|
def on_while(node)
|
75
77
|
check(node)
|
76
78
|
end
|
@@ -223,11 +225,7 @@ module RuboCop
|
|
223
225
|
adjustment = delta + @reindented_lines[lineno]
|
224
226
|
@reindented_lines[lineno] = adjustment
|
225
227
|
|
226
|
-
if adjustment.positive?
|
227
|
-
corrector.remove_leading(buffer.line_range(lineno), adjustment)
|
228
|
-
elsif adjustment.negative?
|
229
|
-
corrector.insert_before(buffer.line_range(lineno), ' ' * -adjustment)
|
230
|
-
end
|
228
|
+
corrector.remove_leading(buffer.line_range(lineno), adjustment) if adjustment.positive?
|
231
229
|
end
|
232
230
|
end
|
233
231
|
end
|
@@ -3,9 +3,17 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Style
|
6
|
-
# Checks for big numeric literals without _ between groups
|
6
|
+
# Checks for big numeric literals without `_` between groups
|
7
7
|
# of digits in them.
|
8
8
|
#
|
9
|
+
# Additional allowed patterns can be added by adding regexps to
|
10
|
+
# the `AllowedPatterns` configuration. All regexps are treated
|
11
|
+
# as anchored even if the patterns do not contain anchors (so
|
12
|
+
# `\d{4}_\d{4}` will allow `1234_5678` but not `1234_5678_9012`).
|
13
|
+
#
|
14
|
+
# NOTE: Even if `AllowedPatterns` are given, autocorrection will
|
15
|
+
# only correct to the standard pattern of an `_` every 3 digits.
|
16
|
+
#
|
9
17
|
# @example
|
10
18
|
#
|
11
19
|
# # bad
|
@@ -34,6 +42,7 @@ module RuboCop
|
|
34
42
|
#
|
35
43
|
class NumericLiterals < Base
|
36
44
|
include IntegerNode
|
45
|
+
include AllowedPattern
|
37
46
|
extend AutoCorrector
|
38
47
|
|
39
48
|
MSG = 'Use underscores(_) as thousands separator and separate every 3 digits with them.'
|
@@ -59,6 +68,7 @@ module RuboCop
|
|
59
68
|
# TODO: handle non-decimal literals as well
|
60
69
|
return if int.start_with?('0')
|
61
70
|
return if allowed_numbers.include?(int)
|
71
|
+
return if matches_allowed_pattern?(int)
|
62
72
|
return unless int.size >= min_digits
|
63
73
|
|
64
74
|
case int
|
@@ -108,6 +118,11 @@ module RuboCop
|
|
108
118
|
def allowed_numbers
|
109
119
|
cop_config.fetch('AllowedNumbers', []).map(&:to_s)
|
110
120
|
end
|
121
|
+
|
122
|
+
def allowed_patterns
|
123
|
+
# Convert the patterns to be anchored
|
124
|
+
super.map { |regexp| Regexp.new(/\A#{regexp}\z/) }
|
125
|
+
end
|
111
126
|
end
|
112
127
|
end
|
113
128
|
end
|