rubocop 1.54.2 → 1.57.2
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 +3 -1
- data/config/default.yml +30 -8
- data/config/obsoletion.yml +5 -0
- data/lib/rubocop/cli/command/auto_generate_config.rb +10 -5
- data/lib/rubocop/cli.rb +1 -1
- data/lib/rubocop/config_finder.rb +2 -2
- data/lib/rubocop/config_obsoletion/parameter_rule.rb +9 -1
- data/lib/rubocop/cop/autocorrect_logic.rb +3 -1
- data/lib/rubocop/cop/base.rb +1 -1
- data/lib/rubocop/cop/bundler/duplicated_gem.rb +1 -0
- data/lib/rubocop/cop/bundler/duplicated_group.rb +127 -0
- data/lib/rubocop/cop/bundler/ordered_gems.rb +9 -1
- data/lib/rubocop/cop/correctors/lambda_literal_to_method_corrector.rb +7 -4
- data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +9 -1
- data/lib/rubocop/cop/generator/require_file_injector.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/example_description.rb +42 -21
- data/lib/rubocop/cop/internal_affairs/redundant_method_dispatch_node.rb +11 -2
- data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +2 -0
- data/lib/rubocop/cop/layout/dot_position.rb +1 -5
- data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +42 -9
- data/lib/rubocop/cop/layout/end_alignment.rb +7 -1
- data/lib/rubocop/cop/layout/heredoc_indentation.rb +3 -0
- data/lib/rubocop/cop/layout/indentation_width.rb +1 -1
- data/lib/rubocop/cop/layout/leading_comment_space.rb +1 -1
- data/lib/rubocop/cop/layout/line_continuation_leading_space.rb +17 -9
- data/lib/rubocop/cop/layout/line_continuation_spacing.rb +1 -1
- data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +18 -3
- data/lib/rubocop/cop/layout/redundant_line_break.rb +13 -3
- data/lib/rubocop/cop/layout/space_after_not.rb +1 -1
- data/lib/rubocop/cop/layout/space_around_method_call_operator.rb +2 -2
- data/lib/rubocop/cop/layout/space_inside_parens.rb +1 -1
- data/lib/rubocop/cop/lint/debugger.rb +10 -1
- data/lib/rubocop/cop/lint/empty_block.rb +1 -1
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +1 -1
- data/lib/rubocop/cop/lint/mixed_case_range.rb +1 -1
- data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +10 -7
- data/lib/rubocop/cop/lint/redundant_require_statement.rb +4 -0
- data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +20 -4
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +11 -4
- data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +7 -1
- data/lib/rubocop/cop/lint/struct_new_override.rb +12 -12
- data/lib/rubocop/cop/lint/suppressed_exception.rb +1 -1
- data/lib/rubocop/cop/lint/to_enum_arguments.rb +5 -3
- data/lib/rubocop/cop/lint/useless_assignment.rb +38 -12
- data/lib/rubocop/cop/lint/void.rb +29 -11
- data/lib/rubocop/cop/metrics/block_length.rb +1 -1
- data/lib/rubocop/cop/metrics/class_length.rb +8 -3
- data/lib/rubocop/cop/metrics/method_length.rb +1 -1
- data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +2 -2
- data/lib/rubocop/cop/mixin/comments_help.rb +16 -12
- data/lib/rubocop/cop/mixin/def_node.rb +1 -1
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +14 -11
- data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +3 -2
- data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +5 -7
- data/lib/rubocop/cop/mixin/string_help.rb +4 -2
- data/lib/rubocop/cop/naming/file_name.rb +1 -1
- data/lib/rubocop/cop/style/alias.rb +9 -8
- data/lib/rubocop/cop/style/arguments_forwarding.rb +280 -63
- data/lib/rubocop/cop/style/array_intersect.rb +13 -5
- data/lib/rubocop/cop/style/block_delimiters.rb +2 -1
- data/lib/rubocop/cop/style/class_equality_comparison.rb +7 -0
- data/lib/rubocop/cop/style/collection_methods.rb +2 -0
- data/lib/rubocop/cop/style/combinable_loops.rb +4 -2
- data/lib/rubocop/cop/style/concat_array_literals.rb +1 -1
- data/lib/rubocop/cop/style/empty_case_condition.rb +6 -1
- data/lib/rubocop/cop/style/for.rb +1 -1
- data/lib/rubocop/cop/style/format_string.rb +24 -3
- data/lib/rubocop/cop/style/guard_clause.rb +26 -0
- data/lib/rubocop/cop/style/hash_conversion.rb +10 -0
- data/lib/rubocop/cop/style/identical_conditional_branches.rb +25 -3
- data/lib/rubocop/cop/style/lambda_call.rb +5 -0
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +8 -1
- data/lib/rubocop/cop/style/mixin_grouping.rb +1 -1
- data/lib/rubocop/cop/style/multiline_block_chain.rb +1 -1
- data/lib/rubocop/cop/style/multiline_ternary_operator.rb +1 -1
- data/lib/rubocop/cop/style/nested_ternary_operator.rb +3 -11
- data/lib/rubocop/cop/style/open_struct_use.rb +1 -1
- data/lib/rubocop/cop/style/operator_method_call.rb +6 -0
- data/lib/rubocop/cop/style/redundant_argument.rb +6 -1
- data/lib/rubocop/cop/style/redundant_begin.rb +9 -1
- data/lib/rubocop/cop/style/redundant_conditional.rb +1 -9
- data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +93 -5
- data/lib/rubocop/cop/style/redundant_exception.rb +32 -12
- data/lib/rubocop/cop/style/redundant_filter_chain.rb +22 -5
- data/lib/rubocop/cop/style/redundant_parentheses.rb +41 -15
- data/lib/rubocop/cop/style/redundant_return.rb +7 -2
- data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +5 -0
- data/lib/rubocop/cop/style/return_nil.rb +6 -2
- data/lib/rubocop/cop/style/return_nil_in_predicate_method_definition.rb +21 -7
- data/lib/rubocop/cop/style/single_argument_dig.rb +2 -1
- data/lib/rubocop/cop/style/single_line_do_end_block.rb +67 -0
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +3 -1
- data/lib/rubocop/cop/style/string_literals_in_interpolation.rb +30 -5
- data/lib/rubocop/cop/style/symbol_array.rb +35 -15
- data/lib/rubocop/cop/style/yoda_expression.rb +8 -7
- data/lib/rubocop/cop/utils/regexp_ranges.rb +26 -13
- data/lib/rubocop/cop/variable_force/assignment.rb +1 -3
- data/lib/rubocop/file_finder.rb +4 -7
- data/lib/rubocop/formatter/html_formatter.rb +4 -2
- data/lib/rubocop/formatter/junit_formatter.rb +1 -1
- data/lib/rubocop/lsp/routes.rb +36 -21
- data/lib/rubocop/lsp/runtime.rb +20 -3
- data/lib/rubocop/lsp/server.rb +6 -4
- data/lib/rubocop/magic_comment.rb +12 -10
- data/lib/rubocop/result_cache.rb +4 -0
- data/lib/rubocop/rspec/shared_contexts.rb +2 -3
- data/lib/rubocop/runner.rb +5 -3
- data/lib/rubocop/server/cache.rb +1 -0
- data/lib/rubocop/target_finder.rb +6 -2
- data/lib/rubocop/target_ruby.rb +9 -5
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +2 -0
- metadata +12 -10
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: adf1db90b03283f492e0e10f234d54d6efc215a8b182965087313e3954d533dd
|
|
4
|
+
data.tar.gz: fa84dfd9d61e4834df9287e0ba0619622f4b7eb9e229e8de1172bc1742c04df5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 44a683eed5e4b9d26caf4d0c775a6f4ba00960b6aaeee29c3f610320d1471326d650e8fc41ee2725af07b4e6a50bf17d442232134522709ebb2a46ec5b80bf40
|
|
7
|
+
data.tar.gz: d4f5dda0dbf7689c55b39de3922c2bd1a0c40aa62ac1046f06c98a19e7f2719cfea11babd480ba4e9b9ff2203d20422a51f096165d5919bf564e009c3a91c087
|
data/README.md
CHANGED
|
@@ -53,7 +53,7 @@ To prevent an unwanted RuboCop update you might want to use a conservative versi
|
|
|
53
53
|
in your `Gemfile`:
|
|
54
54
|
|
|
55
55
|
```rb
|
|
56
|
-
gem 'rubocop', '~> 1.
|
|
56
|
+
gem 'rubocop', '~> 1.57', require: false
|
|
57
57
|
```
|
|
58
58
|
|
|
59
59
|
See [our versioning policy](https://docs.rubocop.org/rubocop/versioning.html) for further details.
|
|
@@ -67,6 +67,8 @@ $ cd my/cool/ruby/project
|
|
|
67
67
|
$ rubocop
|
|
68
68
|
```
|
|
69
69
|
|
|
70
|
+
You can also use this magic in your favorite editor with RuboCop's [built-in LSP](https://docs.rubocop.org/rubocop/usage/lsp.html).
|
|
71
|
+
|
|
70
72
|
## Documentation
|
|
71
73
|
|
|
72
74
|
You can read a lot more about RuboCop in its [official docs](https://docs.rubocop.org).
|
data/config/default.yml
CHANGED
|
@@ -173,6 +173,16 @@ Bundler/DuplicatedGem:
|
|
|
173
173
|
- '**/Gemfile'
|
|
174
174
|
- '**/gems.rb'
|
|
175
175
|
|
|
176
|
+
Bundler/DuplicatedGroup:
|
|
177
|
+
Description: 'Checks for duplicate group entries in Gemfile.'
|
|
178
|
+
Enabled: true
|
|
179
|
+
Severity: warning
|
|
180
|
+
VersionAdded: '1.56'
|
|
181
|
+
Include:
|
|
182
|
+
- '**/*.gemfile'
|
|
183
|
+
- '**/Gemfile'
|
|
184
|
+
- '**/gems.rb'
|
|
185
|
+
|
|
176
186
|
Bundler/GemComment:
|
|
177
187
|
Description: 'Add a comment describing each gem.'
|
|
178
188
|
Enabled: false
|
|
@@ -2160,7 +2170,9 @@ Lint/RedundantRegexpQuantifiers:
|
|
|
2160
2170
|
Lint/RedundantRequireStatement:
|
|
2161
2171
|
Description: 'Checks for unnecessary `require` statement.'
|
|
2162
2172
|
Enabled: true
|
|
2173
|
+
SafeAutoCorrect: false
|
|
2163
2174
|
VersionAdded: '0.76'
|
|
2175
|
+
VersionChanged: '1.57'
|
|
2164
2176
|
|
|
2165
2177
|
Lint/RedundantSafeNavigation:
|
|
2166
2178
|
Description: 'Checks for redundant safe navigation calls.'
|
|
@@ -3072,6 +3084,7 @@ Style/ArgumentsForwarding:
|
|
|
3072
3084
|
StyleGuide: '#arguments-forwarding'
|
|
3073
3085
|
Enabled: pending
|
|
3074
3086
|
AllowOnlyRestArgument: true
|
|
3087
|
+
UseAnonymousForwarding: true
|
|
3075
3088
|
VersionAdded: '1.1'
|
|
3076
3089
|
|
|
3077
3090
|
Style/ArrayCoercion:
|
|
@@ -3343,7 +3356,9 @@ Style/ClassEqualityComparison:
|
|
|
3343
3356
|
Description: 'Enforces the use of `Object#instance_of?` instead of class comparison for equality.'
|
|
3344
3357
|
StyleGuide: '#instance-of-vs-class-comparison'
|
|
3345
3358
|
Enabled: true
|
|
3359
|
+
SafeAutoCorrect: false
|
|
3346
3360
|
VersionAdded: '0.93'
|
|
3361
|
+
VersionChanged: '1.57'
|
|
3347
3362
|
AllowedMethods:
|
|
3348
3363
|
- ==
|
|
3349
3364
|
- equal?
|
|
@@ -3398,6 +3413,7 @@ Style/CollectionMethods:
|
|
|
3398
3413
|
PreferredMethods:
|
|
3399
3414
|
collect: 'map'
|
|
3400
3415
|
collect!: 'map!'
|
|
3416
|
+
collect_concat: 'flat_map'
|
|
3401
3417
|
inject: 'reduce'
|
|
3402
3418
|
detect: 'find'
|
|
3403
3419
|
find_all: 'select'
|
|
@@ -3916,8 +3932,9 @@ Style/HashConversion:
|
|
|
3916
3932
|
Description: 'Avoid Hash[] in favor of ary.to_h or literal hashes.'
|
|
3917
3933
|
StyleGuide: '#avoid-hash-constructor'
|
|
3918
3934
|
Enabled: pending
|
|
3935
|
+
SafeAutoCorrect: false
|
|
3919
3936
|
VersionAdded: '1.10'
|
|
3920
|
-
VersionChanged: '1.
|
|
3937
|
+
VersionChanged: '1.55'
|
|
3921
3938
|
AllowSplatArgument: true
|
|
3922
3939
|
|
|
3923
3940
|
Style/HashEachMethods:
|
|
@@ -4118,12 +4135,6 @@ Style/InvertibleUnlessCondition:
|
|
|
4118
4135
|
:none?: :any?
|
|
4119
4136
|
:even?: :odd?
|
|
4120
4137
|
:odd?: :even?
|
|
4121
|
-
# `ActiveSupport` defines some common inverse methods. They are listed below,
|
|
4122
|
-
# and not enabled by default.
|
|
4123
|
-
# :present?: :blank?
|
|
4124
|
-
# :blank?: :present?
|
|
4125
|
-
# :include?: :exclude?
|
|
4126
|
-
# :exclude?: :include?
|
|
4127
4138
|
|
|
4128
4139
|
Style/IpAddresses:
|
|
4129
4140
|
Description: "Don't include literal IP addresses in code."
|
|
@@ -4810,12 +4821,16 @@ Style/RedundantArgument:
|
|
|
4810
4821
|
Enabled: pending
|
|
4811
4822
|
Safe: false
|
|
4812
4823
|
VersionAdded: '1.4'
|
|
4813
|
-
VersionChanged: '1.
|
|
4824
|
+
VersionChanged: '1.55'
|
|
4814
4825
|
Methods:
|
|
4815
4826
|
# Array#join
|
|
4816
4827
|
join: ''
|
|
4817
4828
|
# Array#sum
|
|
4818
4829
|
sum: 0
|
|
4830
|
+
# Kernel.#exit
|
|
4831
|
+
exit: true
|
|
4832
|
+
# Kernel.#exit!
|
|
4833
|
+
exit!: false
|
|
4819
4834
|
# String#split
|
|
4820
4835
|
split: ' '
|
|
4821
4836
|
# String#chomp
|
|
@@ -4909,7 +4924,9 @@ Style/RedundantFilterChain:
|
|
|
4909
4924
|
Identifies usages of `any?`, `empty?`, `none?` or `one?` predicate methods chained to
|
|
4910
4925
|
`select`/`filter`/`find_all` and change them to use predicate method instead.
|
|
4911
4926
|
Enabled: pending
|
|
4927
|
+
SafeAutoCorrect: false
|
|
4912
4928
|
VersionAdded: '1.52'
|
|
4929
|
+
VersionChanged: '1.57'
|
|
4913
4930
|
|
|
4914
4931
|
Style/RedundantFreeze:
|
|
4915
4932
|
Description: "Checks usages of Object#freeze on immutable objects."
|
|
@@ -5171,6 +5188,11 @@ Style/SingleLineBlockParams:
|
|
|
5171
5188
|
- acc
|
|
5172
5189
|
- elem
|
|
5173
5190
|
|
|
5191
|
+
Style/SingleLineDoEndBlock:
|
|
5192
|
+
Description: 'Checks for single-line `do`...`end` blocks.'
|
|
5193
|
+
Enabled: pending
|
|
5194
|
+
VersionAdded: '1.57'
|
|
5195
|
+
|
|
5174
5196
|
Style/SingleLineMethods:
|
|
5175
5197
|
Description: 'Avoid single-line methods.'
|
|
5176
5198
|
StyleGuide: '#no-single-line-methods'
|
data/config/obsoletion.yml
CHANGED
|
@@ -224,6 +224,11 @@ changed_parameters:
|
|
|
224
224
|
- AllowedMethods
|
|
225
225
|
- AllowedPatterns
|
|
226
226
|
severity: warning
|
|
227
|
+
- cops: Style/ArgumentsForwarding
|
|
228
|
+
parameters: AllowOnlyRestArgument
|
|
229
|
+
reason: "`AllowOnlyRestArgument` has no effect with TargetRubyVersion >= 3.2."
|
|
230
|
+
severity: warning
|
|
231
|
+
minimum_ruby_version: 3.2
|
|
227
232
|
|
|
228
233
|
# Enforced styles that have been removed or replaced
|
|
229
234
|
changed_enforced_styles:
|
|
@@ -10,6 +10,7 @@ module RuboCop
|
|
|
10
10
|
|
|
11
11
|
AUTO_GENERATED_FILE = '.rubocop_todo.yml'
|
|
12
12
|
YAML_OPTIONAL_DOC_START = /\A---(\s+#|\s*\z)/.freeze
|
|
13
|
+
PLACEHOLDER = '###rubocop:inherit_here'
|
|
13
14
|
|
|
14
15
|
PHASE_1 = 'Phase 1 of 2: run Layout/LineLength cop'
|
|
15
16
|
PHASE_2 = 'Phase 2 of 2: run all cops'
|
|
@@ -125,15 +126,19 @@ module RuboCop
|
|
|
125
126
|
|
|
126
127
|
def existing_configuration(config_file)
|
|
127
128
|
File.read(config_file, encoding: Encoding::UTF_8)
|
|
128
|
-
.sub(/^inherit_from: *[^\n]+/,
|
|
129
|
-
.sub(/^inherit_from: *(\n *- *[^\n]+)+/,
|
|
129
|
+
.sub(/^inherit_from: *[^\n]+/, PLACEHOLDER)
|
|
130
|
+
.sub(/^inherit_from: *(\n *- *[^\n]+)+/, PLACEHOLDER)
|
|
130
131
|
end
|
|
131
132
|
|
|
132
133
|
def write_config_file(file_name, file_string, rubocop_yml_contents)
|
|
133
134
|
lines = /\S/.match?(rubocop_yml_contents) ? rubocop_yml_contents.split("\n", -1) : []
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
135
|
+
unless rubocop_yml_contents&.include?(PLACEHOLDER)
|
|
136
|
+
doc_start_index = lines.index { |line| YAML_OPTIONAL_DOC_START.match?(line) } || -1
|
|
137
|
+
lines.insert(doc_start_index + 1, PLACEHOLDER)
|
|
138
|
+
end
|
|
139
|
+
File.write(file_name, lines.join("\n")
|
|
140
|
+
.sub(/#{PLACEHOLDER}\n*/o, "inherit_from:#{file_string}\n\n")
|
|
141
|
+
.sub(/\n\n+\Z/, "\n"))
|
|
137
142
|
end
|
|
138
143
|
|
|
139
144
|
def relative_path_to_todo_from_options_config
|
data/lib/rubocop/cli.rb
CHANGED
|
@@ -11,7 +11,7 @@ module RuboCop
|
|
|
11
11
|
STATUS_ERROR = 2
|
|
12
12
|
STATUS_INTERRUPTED = Signal.list['INT'] + 128
|
|
13
13
|
DEFAULT_PARALLEL_OPTIONS = %i[
|
|
14
|
-
color debug display_style_guide display_time display_only_fail_level_offenses
|
|
14
|
+
color config debug display_style_guide display_time display_only_fail_level_offenses
|
|
15
15
|
display_only_failed except extra_details fail_level fix_layout format
|
|
16
16
|
ignore_disable_comments lint only only_guide_cops require safe
|
|
17
17
|
autocorrect safe_autocorrect autocorrect_all
|
|
@@ -46,14 +46,14 @@ module RuboCop
|
|
|
46
46
|
|
|
47
47
|
file = File.join(Dir.home, DOTFILE)
|
|
48
48
|
|
|
49
|
-
|
|
49
|
+
file if File.exist?(file)
|
|
50
50
|
end
|
|
51
51
|
|
|
52
52
|
def find_user_xdg_config
|
|
53
53
|
xdg_config_home = expand_path(ENV.fetch('XDG_CONFIG_HOME', '~/.config'))
|
|
54
54
|
xdg_config = File.join(xdg_config_home, 'rubocop', XDG_CONFIG)
|
|
55
55
|
|
|
56
|
-
|
|
56
|
+
xdg_config if File.exist?(xdg_config)
|
|
57
57
|
end
|
|
58
58
|
|
|
59
59
|
def expand_path(path)
|
|
@@ -19,7 +19,7 @@ module RuboCop
|
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
def violated?
|
|
22
|
-
config[cop]&.key?(parameter)
|
|
22
|
+
applies_to_current_ruby_version? && config[cop]&.key?(parameter)
|
|
23
23
|
end
|
|
24
24
|
|
|
25
25
|
def warning?
|
|
@@ -28,6 +28,14 @@ module RuboCop
|
|
|
28
28
|
|
|
29
29
|
private
|
|
30
30
|
|
|
31
|
+
def applies_to_current_ruby_version?
|
|
32
|
+
minimum_ruby_version = metadata['minimum_ruby_version']
|
|
33
|
+
|
|
34
|
+
return true unless minimum_ruby_version
|
|
35
|
+
|
|
36
|
+
config.target_ruby_version >= minimum_ruby_version
|
|
37
|
+
end
|
|
38
|
+
|
|
31
39
|
def alternative
|
|
32
40
|
metadata['alternative']
|
|
33
41
|
end
|
|
@@ -82,7 +82,9 @@ module RuboCop
|
|
|
82
82
|
node.array_type? && node.percent_literal?
|
|
83
83
|
end
|
|
84
84
|
|
|
85
|
-
percent_array.map(&:source_range).find
|
|
85
|
+
percent_array.map(&:source_range).find do |range|
|
|
86
|
+
offense_range.begin_pos > range.begin_pos && range.overlaps?(offense_range)
|
|
87
|
+
end
|
|
86
88
|
end
|
|
87
89
|
|
|
88
90
|
def range_of_first_line(range)
|
data/lib/rubocop/cop/base.rb
CHANGED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module Cop
|
|
5
|
+
module Bundler
|
|
6
|
+
# A Gem group, or a set of groups, should be listed only once in a Gemfile.
|
|
7
|
+
#
|
|
8
|
+
# For example, if the values of `source`, `git`, `platforms`, or `path`
|
|
9
|
+
# surrounding `group` are different, no offense will be registered:
|
|
10
|
+
#
|
|
11
|
+
# [source,ruby]
|
|
12
|
+
# -----
|
|
13
|
+
# platforms :ruby do
|
|
14
|
+
# group :default do
|
|
15
|
+
# gem 'openssl'
|
|
16
|
+
# end
|
|
17
|
+
# end
|
|
18
|
+
#
|
|
19
|
+
# platforms :jruby do
|
|
20
|
+
# group :default do
|
|
21
|
+
# gem 'jruby-openssl'
|
|
22
|
+
# end
|
|
23
|
+
# end
|
|
24
|
+
# -----
|
|
25
|
+
#
|
|
26
|
+
# @example
|
|
27
|
+
# # bad
|
|
28
|
+
# group :development do
|
|
29
|
+
# gem 'rubocop'
|
|
30
|
+
# end
|
|
31
|
+
#
|
|
32
|
+
# group :development do
|
|
33
|
+
# gem 'rubocop-rails'
|
|
34
|
+
# end
|
|
35
|
+
#
|
|
36
|
+
# # bad (same set of groups declared twice)
|
|
37
|
+
# group :development, :test do
|
|
38
|
+
# gem 'rubocop'
|
|
39
|
+
# end
|
|
40
|
+
#
|
|
41
|
+
# group :test, :development do
|
|
42
|
+
# gem 'rspec'
|
|
43
|
+
# end
|
|
44
|
+
#
|
|
45
|
+
# # good
|
|
46
|
+
# group :development do
|
|
47
|
+
# gem 'rubocop'
|
|
48
|
+
# end
|
|
49
|
+
#
|
|
50
|
+
# group :development, :test do
|
|
51
|
+
# gem 'rspec'
|
|
52
|
+
# end
|
|
53
|
+
#
|
|
54
|
+
# # good
|
|
55
|
+
# gem 'rubocop', groups: [:development, :test]
|
|
56
|
+
# gem 'rspec', groups: [:development, :test]
|
|
57
|
+
#
|
|
58
|
+
class DuplicatedGroup < Base
|
|
59
|
+
include RangeHelp
|
|
60
|
+
|
|
61
|
+
MSG = 'Gem group `%<group_name>s` already defined on line ' \
|
|
62
|
+
'%<line_of_first_occurrence>d of the Gemfile.'
|
|
63
|
+
SOURCE_BLOCK_NAMES = %i[source git platforms path].freeze
|
|
64
|
+
|
|
65
|
+
# @!method group_declarations(node)
|
|
66
|
+
def_node_search :group_declarations, '(send nil? :group ...)'
|
|
67
|
+
|
|
68
|
+
def on_new_investigation
|
|
69
|
+
return if processed_source.blank?
|
|
70
|
+
|
|
71
|
+
duplicated_group_nodes.each do |nodes|
|
|
72
|
+
nodes[1..].each do |node|
|
|
73
|
+
group_name = node.arguments.map(&:source).join(', ')
|
|
74
|
+
|
|
75
|
+
register_offense(node, group_name, nodes.first.first_line)
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
private
|
|
81
|
+
|
|
82
|
+
def duplicated_group_nodes
|
|
83
|
+
group_declarations = group_declarations(processed_source.ast)
|
|
84
|
+
group_keys = group_declarations.group_by do |node|
|
|
85
|
+
source_key = find_source_key(node)
|
|
86
|
+
group_attributes = group_attributes(node).sort.join
|
|
87
|
+
|
|
88
|
+
"#{source_key}#{group_attributes}"
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
group_keys.values.select { |nodes| nodes.size > 1 }
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def register_offense(node, group_name, line_of_first_occurrence)
|
|
95
|
+
line_range = node.loc.column...node.loc.last_column
|
|
96
|
+
offense_location = source_range(processed_source.buffer, node.first_line, line_range)
|
|
97
|
+
message = format(
|
|
98
|
+
MSG,
|
|
99
|
+
group_name: group_name,
|
|
100
|
+
line_of_first_occurrence: line_of_first_occurrence
|
|
101
|
+
)
|
|
102
|
+
add_offense(offense_location, message: message)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def find_source_key(node)
|
|
106
|
+
source_block = node.each_ancestor(:block).find do |block_node|
|
|
107
|
+
SOURCE_BLOCK_NAMES.include?(block_node.method_name)
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
return unless source_block
|
|
111
|
+
|
|
112
|
+
"#{source_block.method_name}#{source_block.send_node.first_argument&.source}"
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def group_attributes(node)
|
|
116
|
+
node.arguments.map do |argument|
|
|
117
|
+
if argument.hash_type?
|
|
118
|
+
argument.pairs.map(&:source).sort.join(', ')
|
|
119
|
+
else
|
|
120
|
+
argument.respond_to?(:value) ? argument.value.to_s : argument.source
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
@@ -19,7 +19,15 @@ module RuboCop
|
|
|
19
19
|
#
|
|
20
20
|
# gem 'rspec'
|
|
21
21
|
#
|
|
22
|
-
#
|
|
22
|
+
# @example TreatCommentsAsGroupSeparators: true (default)
|
|
23
|
+
# # good
|
|
24
|
+
# # For code quality
|
|
25
|
+
# gem 'rubocop'
|
|
26
|
+
# # For tests
|
|
27
|
+
# gem 'rspec'
|
|
28
|
+
#
|
|
29
|
+
# @example TreatCommentsAsGroupSeparators: false
|
|
30
|
+
# # bad
|
|
23
31
|
# # For code quality
|
|
24
32
|
# gem 'rubocop'
|
|
25
33
|
# # For tests
|
|
@@ -14,12 +14,15 @@ module RuboCop
|
|
|
14
14
|
# Check for unparenthesized args' preceding and trailing whitespaces.
|
|
15
15
|
remove_unparenthesized_whitespace(corrector)
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
if block_node.block_type?
|
|
18
|
+
# Avoid correcting to `lambdado` by inserting whitespace
|
|
19
|
+
# if none exists before or after the lambda arguments.
|
|
20
|
+
insert_separating_space(corrector)
|
|
21
|
+
|
|
22
|
+
remove_arguments(corrector)
|
|
23
|
+
end
|
|
20
24
|
|
|
21
25
|
replace_selector(corrector)
|
|
22
|
-
remove_arguments(corrector)
|
|
23
26
|
|
|
24
27
|
replace_delimiters(corrector)
|
|
25
28
|
|
|
@@ -45,7 +45,15 @@ module RuboCop
|
|
|
45
45
|
#
|
|
46
46
|
# spec.add_runtime_dependency 'rspec'
|
|
47
47
|
#
|
|
48
|
-
#
|
|
48
|
+
# @example TreatCommentsAsGroupSeparators: true (default)
|
|
49
|
+
# # good
|
|
50
|
+
# # For code quality
|
|
51
|
+
# spec.add_dependency 'rubocop'
|
|
52
|
+
# # For tests
|
|
53
|
+
# spec.add_dependency 'rspec'
|
|
54
|
+
#
|
|
55
|
+
# @example TreatCommentsAsGroupSeparators: false
|
|
56
|
+
# # bad
|
|
49
57
|
# # For code quality
|
|
50
58
|
# spec.add_dependency 'rubocop'
|
|
51
59
|
# # For tests
|
|
@@ -26,9 +26,7 @@ module RuboCop
|
|
|
26
26
|
# expect_no_offenses('...')
|
|
27
27
|
# end
|
|
28
28
|
class ExampleDescription < Base
|
|
29
|
-
|
|
30
|
-
attr_accessor :descriptions
|
|
31
|
-
end
|
|
29
|
+
extend AutoCorrector
|
|
32
30
|
|
|
33
31
|
MSG = 'Description does not match use of `%<method_name>s`.'
|
|
34
32
|
|
|
@@ -39,21 +37,31 @@ module RuboCop
|
|
|
39
37
|
expect_no_corrections
|
|
40
38
|
].to_set.freeze
|
|
41
39
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
40
|
+
EXPECT_NO_OFFENSES_DESCRIPTION_MAPPING = {
|
|
41
|
+
/\A(adds|registers|reports|finds) (an? )?offense/ => 'does not register an offense',
|
|
42
|
+
/\A(flags|handles|works)\b/ => 'does not register'
|
|
43
|
+
}.freeze
|
|
44
|
+
|
|
45
|
+
EXPECT_OFFENSE_DESCRIPTION_MAPPING = {
|
|
46
|
+
/\A(does not|doesn't) (register|find|flag|report)/ => 'registers',
|
|
47
|
+
/\A(does not|doesn't) add (a|an|any )?offense/ => 'registers an offense',
|
|
48
|
+
/\Aaccepts\b/ => 'registers'
|
|
49
|
+
}.freeze
|
|
46
50
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
].freeze
|
|
51
|
+
EXPECT_NO_CORRECTIONS_DESCRIPTION_MAPPING = {
|
|
52
|
+
/\A(auto[- ]?)?correct/ => 'does not correct'
|
|
53
|
+
}.freeze
|
|
51
54
|
|
|
52
|
-
|
|
55
|
+
EXPECT_CORRECTION_DESCRIPTION_MAPPING = {
|
|
56
|
+
/\b(does not|doesn't) (auto[- ]?)?correct/ => 'autocorrects'
|
|
57
|
+
}.freeze
|
|
53
58
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
59
|
+
EXAMPLE_DESCRIPTION_MAPPING = {
|
|
60
|
+
expect_no_offenses: EXPECT_NO_OFFENSES_DESCRIPTION_MAPPING,
|
|
61
|
+
expect_offense: EXPECT_OFFENSE_DESCRIPTION_MAPPING,
|
|
62
|
+
expect_no_corrections: EXPECT_NO_CORRECTIONS_DESCRIPTION_MAPPING,
|
|
63
|
+
expect_correction: EXPECT_CORRECTION_DESCRIPTION_MAPPING
|
|
64
|
+
}.freeze
|
|
57
65
|
|
|
58
66
|
# @!method offense_example?(node)
|
|
59
67
|
def_node_matcher :offense_example?, <<~PATTERN
|
|
@@ -66,21 +74,34 @@ module RuboCop
|
|
|
66
74
|
|
|
67
75
|
def on_send(node)
|
|
68
76
|
parent = node.each_ancestor(:block).first
|
|
69
|
-
return unless parent && (
|
|
77
|
+
return unless parent && (current_description = offense_example?(parent))
|
|
70
78
|
|
|
71
79
|
method_name = node.method_name
|
|
72
80
|
message = format(MSG, method_name: method_name)
|
|
73
81
|
|
|
74
|
-
|
|
75
|
-
check_description(
|
|
82
|
+
description_map = EXAMPLE_DESCRIPTION_MAPPING[method_name]
|
|
83
|
+
check_description(current_description, description_map, message)
|
|
76
84
|
end
|
|
77
85
|
|
|
78
86
|
private
|
|
79
87
|
|
|
80
|
-
def check_description(
|
|
81
|
-
|
|
88
|
+
def check_description(current_description, description_map, message)
|
|
89
|
+
description_text = string_contents(current_description)
|
|
90
|
+
return unless (new_description = correct_description(description_text, description_map))
|
|
91
|
+
|
|
92
|
+
add_offense(current_description, message: message) do |corrector|
|
|
93
|
+
corrector.replace(current_description, "'#{new_description}'")
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def correct_description(current_description, description_map)
|
|
98
|
+
description_map.each do |incorrect_description_pattern, preferred_description|
|
|
99
|
+
if incorrect_description_pattern.match?(current_description)
|
|
100
|
+
return current_description.gsub(incorrect_description_pattern, preferred_description)
|
|
101
|
+
end
|
|
102
|
+
end
|
|
82
103
|
|
|
83
|
-
|
|
104
|
+
nil
|
|
84
105
|
end
|
|
85
106
|
|
|
86
107
|
def string_contents(node)
|
|
@@ -14,6 +14,12 @@ module RuboCop
|
|
|
14
14
|
# node.method_name
|
|
15
15
|
#
|
|
16
16
|
# # bad
|
|
17
|
+
# node.send_node.method?(:method_name)
|
|
18
|
+
#
|
|
19
|
+
# # good
|
|
20
|
+
# node.method?(:method_name)
|
|
21
|
+
#
|
|
22
|
+
# # bad
|
|
17
23
|
# node.send_node.receiver
|
|
18
24
|
#
|
|
19
25
|
# # good
|
|
@@ -24,11 +30,14 @@ module RuboCop
|
|
|
24
30
|
extend AutoCorrector
|
|
25
31
|
|
|
26
32
|
MSG = 'Remove the redundant `send_node`.'
|
|
27
|
-
RESTRICT_ON_SEND = %i[method_name receiver].freeze
|
|
33
|
+
RESTRICT_ON_SEND = %i[method_name method? receiver].freeze
|
|
28
34
|
|
|
29
35
|
# @!method dispatch_method(node)
|
|
30
36
|
def_node_matcher :dispatch_method, <<~PATTERN
|
|
31
|
-
|
|
37
|
+
{
|
|
38
|
+
(send $(send _ :send_node) {:method_name :receiver})
|
|
39
|
+
(send $(send _ :send_node) :method? _)
|
|
40
|
+
}
|
|
32
41
|
PATTERN
|
|
33
42
|
|
|
34
43
|
def on_send(node)
|
|
@@ -32,7 +32,7 @@ module RuboCop
|
|
|
32
32
|
end
|
|
33
33
|
|
|
34
34
|
def on_send(node)
|
|
35
|
-
return unless node.dot? ||
|
|
35
|
+
return unless node.dot? || node.safe_navigation?
|
|
36
36
|
|
|
37
37
|
return correct_style_detected if proper_dot_position?(node)
|
|
38
38
|
|
|
@@ -133,10 +133,6 @@ module RuboCop
|
|
|
133
133
|
# l.(1) has no selector, so we use the opening parenthesis instead
|
|
134
134
|
node.loc.selector || node.loc.begin
|
|
135
135
|
end
|
|
136
|
-
|
|
137
|
-
def ampersand_dot?(node)
|
|
138
|
-
node.loc.respond_to?(:dot) && node.loc.dot && node.loc.dot.is?('&.')
|
|
139
|
-
end
|
|
140
136
|
end
|
|
141
137
|
end
|
|
142
138
|
end
|