rubocop 1.69.2 → 1.71.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/LICENSE.txt +1 -1
- data/README.md +2 -2
- data/config/default.yml +36 -2
- data/lib/rubocop/cli/command/execute_runner.rb +3 -3
- data/lib/rubocop/cli/command/show_cops.rb +24 -2
- data/lib/rubocop/comment_config.rb +1 -1
- data/lib/rubocop/config.rb +13 -4
- data/lib/rubocop/config_loader.rb +4 -0
- data/lib/rubocop/config_loader_resolver.rb +14 -3
- data/lib/rubocop/config_validator.rb +18 -8
- data/lib/rubocop/cop/base.rb +6 -0
- data/lib/rubocop/cop/bundler/gem_comment.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/cop_enabled.rb +85 -0
- data/lib/rubocop/cop/internal_affairs/location_expression.rb +2 -1
- data/lib/rubocop/cop/internal_affairs/node_first_or_last_argument.rb +3 -2
- data/lib/rubocop/cop/internal_affairs/node_type_predicate.rb +4 -3
- data/lib/rubocop/cop/internal_affairs/on_send_without_on_csend.rb +90 -0
- data/lib/rubocop/cop/internal_affairs/redundant_source_range.rb +2 -1
- data/lib/rubocop/cop/internal_affairs/single_line_comparison.rb +5 -4
- data/lib/rubocop/cop/internal_affairs.rb +2 -0
- data/lib/rubocop/cop/layout/argument_alignment.rb +2 -8
- data/lib/rubocop/cop/layout/class_structure.rb +7 -7
- data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +1 -0
- data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +1 -1
- data/lib/rubocop/cop/layout/extra_spacing.rb +1 -1
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +2 -7
- data/lib/rubocop/cop/layout/first_array_element_indentation.rb +2 -7
- data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +2 -7
- data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +1 -1
- data/lib/rubocop/cop/layout/hash_alignment.rb +6 -4
- data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +1 -0
- data/lib/rubocop/cop/layout/line_continuation_spacing.rb +7 -1
- data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/line_length.rb +1 -0
- data/lib/rubocop/cop/layout/multiline_hash_key_line_breaks.rb +1 -1
- data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +25 -0
- data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +1 -0
- data/lib/rubocop/cop/layout/redundant_line_break.rb +1 -1
- data/lib/rubocop/cop/layout/space_after_method_name.rb +1 -1
- data/lib/rubocop/cop/layout/space_around_keyword.rb +1 -0
- data/lib/rubocop/cop/layout/space_around_operators.rb +3 -3
- data/lib/rubocop/cop/layout/trailing_whitespace.rb +5 -3
- data/lib/rubocop/cop/lint/array_literal_in_regexp.rb +119 -0
- data/lib/rubocop/cop/lint/constant_reassignment.rb +152 -0
- data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +1 -1
- data/lib/rubocop/cop/lint/duplicate_set_element.rb +20 -7
- data/lib/rubocop/cop/lint/float_comparison.rb +5 -2
- data/lib/rubocop/cop/lint/float_out_of_range.rb +1 -1
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +23 -5
- data/lib/rubocop/cop/lint/mixed_case_range.rb +1 -1
- data/lib/rubocop/cop/lint/mixed_regexp_capture_types.rb +1 -1
- data/lib/rubocop/cop/lint/nested_method_definition.rb +5 -1
- data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +4 -3
- data/lib/rubocop/cop/lint/numeric_operation_with_constant_result.rb +17 -30
- data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +2 -1
- data/lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_string_coercion.rb +2 -2
- data/lib/rubocop/cop/lint/rescue_exception.rb +1 -1
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +7 -0
- data/lib/rubocop/cop/lint/shared_mutable_default.rb +65 -0
- data/lib/rubocop/cop/lint/syntax.rb +4 -1
- data/lib/rubocop/cop/lint/unescaped_bracket_in_regexp.rb +1 -4
- data/lib/rubocop/cop/lint/useless_assignment.rb +1 -1
- data/lib/rubocop/cop/lint/useless_numeric_operation.rb +2 -1
- data/lib/rubocop/cop/lint/void.rb +3 -2
- data/lib/rubocop/cop/metrics/collection_literal_length.rb +7 -0
- data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +1 -1
- data/lib/rubocop/cop/metrics/method_length.rb +8 -1
- data/lib/rubocop/cop/metrics/perceived_complexity.rb +1 -1
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +7 -7
- data/lib/rubocop/cop/mixin/comments_help.rb +2 -0
- data/lib/rubocop/cop/mixin/dig_help.rb +1 -1
- data/lib/rubocop/cop/mixin/frozen_string_literal.rb +1 -1
- data/lib/rubocop/cop/mixin/hash_subset.rb +170 -0
- data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +26 -16
- data/lib/rubocop/cop/mixin/space_before_punctuation.rb +1 -1
- data/lib/rubocop/cop/mixin/statement_modifier.rb +8 -3
- data/lib/rubocop/cop/mixin/string_literals_help.rb +1 -1
- data/lib/rubocop/cop/mixin/trailing_comma.rb +2 -2
- data/lib/rubocop/cop/naming/block_forwarding.rb +1 -1
- data/lib/rubocop/cop/security/compound_hash.rb +1 -0
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +32 -1
- data/lib/rubocop/cop/style/and_or.rb +1 -1
- data/lib/rubocop/cop/style/arguments_forwarding.rb +1 -4
- data/lib/rubocop/cop/style/array_first_last.rb +18 -2
- data/lib/rubocop/cop/style/block_delimiters.rb +6 -19
- data/lib/rubocop/cop/style/class_and_module_children.rb +5 -2
- data/lib/rubocop/cop/style/collection_methods.rb +1 -1
- data/lib/rubocop/cop/style/conditional_assignment.rb +3 -1
- data/lib/rubocop/cop/style/each_for_simple_loop.rb +4 -7
- data/lib/rubocop/cop/style/empty_else.rb +4 -2
- data/lib/rubocop/cop/style/empty_literal.rb +1 -1
- data/lib/rubocop/cop/style/empty_method.rb +1 -1
- data/lib/rubocop/cop/style/exact_regexp_match.rb +3 -10
- data/lib/rubocop/cop/style/exponential_notation.rb +1 -1
- data/lib/rubocop/cop/style/fetch_env_var.rb +1 -1
- data/lib/rubocop/cop/style/float_division.rb +8 -4
- data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +1 -1
- data/lib/rubocop/cop/style/hash_each_methods.rb +1 -1
- data/lib/rubocop/cop/style/hash_except.rb +9 -148
- data/lib/rubocop/cop/style/hash_slice.rb +65 -0
- data/lib/rubocop/cop/style/hash_syntax.rb +5 -2
- data/lib/rubocop/cop/style/it_assignment.rb +36 -0
- data/lib/rubocop/cop/style/map_to_set.rb +3 -2
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +11 -1
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +2 -0
- data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +2 -1
- data/lib/rubocop/cop/style/missing_else.rb +2 -0
- data/lib/rubocop/cop/style/multiple_comparison.rb +26 -20
- data/lib/rubocop/cop/style/mutable_constant.rb +2 -2
- data/lib/rubocop/cop/style/object_then.rb +13 -15
- data/lib/rubocop/cop/style/open_struct_use.rb +4 -4
- data/lib/rubocop/cop/style/quoted_symbols.rb +1 -1
- data/lib/rubocop/cop/style/raise_args.rb +6 -4
- data/lib/rubocop/cop/style/random_with_offset.rb +3 -3
- data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +2 -1
- data/lib/rubocop/cop/style/redundant_exception.rb +1 -1
- data/lib/rubocop/cop/style/redundant_freeze.rb +1 -1
- data/lib/rubocop/cop/style/redundant_initialize.rb +12 -3
- data/lib/rubocop/cop/style/redundant_line_continuation.rb +34 -13
- data/lib/rubocop/cop/style/redundant_parentheses.rb +4 -4
- data/lib/rubocop/cop/style/redundant_regexp_argument.rb +3 -0
- data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +1 -1
- data/lib/rubocop/cop/style/redundant_regexp_escape.rb +1 -1
- data/lib/rubocop/cop/style/redundant_self_assignment.rb +6 -5
- data/lib/rubocop/cop/style/safe_navigation.rb +1 -1
- data/lib/rubocop/cop/style/send_with_literal_method_name.rb +2 -1
- data/lib/rubocop/cop/style/single_line_block_params.rb +1 -1
- data/lib/rubocop/cop/style/single_line_do_end_block.rb +1 -2
- data/lib/rubocop/cop/style/single_line_methods.rb +2 -3
- data/lib/rubocop/cop/style/slicing_with_range.rb +40 -11
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +1 -1
- data/lib/rubocop/cop/style/string_methods.rb +1 -1
- data/lib/rubocop/cop/style/super_arguments.rb +63 -15
- data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +4 -1
- data/lib/rubocop/cop/style/yoda_condition.rb +8 -4
- data/lib/rubocop/cop/style/yoda_expression.rb +1 -0
- data/lib/rubocop/cop/util.rb +9 -2
- data/lib/rubocop/cops_documentation_generator.rb +13 -13
- data/lib/rubocop/directive_comment.rb +9 -8
- data/lib/rubocop/formatter/formatter_set.rb +1 -1
- data/lib/rubocop/lsp/diagnostic.rb +189 -0
- data/lib/rubocop/lsp/logger.rb +2 -2
- data/lib/rubocop/lsp/routes.rb +7 -23
- data/lib/rubocop/lsp/runtime.rb +15 -49
- data/lib/rubocop/lsp/stdin_runner.rb +83 -0
- data/lib/rubocop/options.rb +2 -1
- data/lib/rubocop/path_util.rb +11 -8
- data/lib/rubocop/result_cache.rb +13 -13
- data/lib/rubocop/rspec/expect_offense.rb +6 -2
- data/lib/rubocop/rspec/shared_contexts.rb +4 -1
- data/lib/rubocop/runner.rb +5 -6
- data/lib/rubocop/target_finder.rb +1 -0
- data/lib/rubocop/target_ruby.rb +15 -0
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +6 -0
- data/lib/ruby_lsp/rubocop/addon.rb +78 -0
- data/lib/ruby_lsp/rubocop/wraps_built_in_lsp_runtime.rb +50 -0
- metadata +17 -8
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0f4339f6b223b2a7fd5f68764dd3030e5cb83925c0605414459ed0f3d2543510
|
|
4
|
+
data.tar.gz: 525042279be387c345b3efd57ed7ca976e3eda5b15ba9723485b72f3a083816e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 404c792e4624474f907576ef9c73fc3ee09a5736c63becf75197fe40d5e9fdefb7c2cb6bc22326857d3b5065f50badd1a6a4d8f7cecd219fb6ec7280bb95a97a
|
|
7
|
+
data.tar.gz: 6e3071938d0f6d7850a732c41ce55890c6a2ba8bcd352df28203c136453cf249fd21a10c9c3d1ea7762376466a669a287efb56c8b7505877d8b17cacdd5dd059
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
|
@@ -52,7 +52,7 @@ To prevent an unwanted RuboCop update you might want to use a conservative versi
|
|
|
52
52
|
in your `Gemfile`:
|
|
53
53
|
|
|
54
54
|
```rb
|
|
55
|
-
gem 'rubocop', '~> 1.
|
|
55
|
+
gem 'rubocop', '~> 1.71', require: false
|
|
56
56
|
```
|
|
57
57
|
|
|
58
58
|
See [our versioning policy](https://docs.rubocop.org/rubocop/versioning.html) for further details.
|
|
@@ -247,5 +247,5 @@ RuboCop's changelog is available [here](CHANGELOG.md).
|
|
|
247
247
|
|
|
248
248
|
## Copyright
|
|
249
249
|
|
|
250
|
-
Copyright (c) 2012-
|
|
250
|
+
Copyright (c) 2012-2025 Bozhidar Batsov. See [LICENSE.txt](LICENSE.txt) for
|
|
251
251
|
further details.
|
data/config/default.yml
CHANGED
|
@@ -1616,6 +1616,12 @@ Lint/AmbiguousRegexpLiteral:
|
|
|
1616
1616
|
VersionAdded: '0.17'
|
|
1617
1617
|
VersionChanged: '0.83'
|
|
1618
1618
|
|
|
1619
|
+
Lint/ArrayLiteralInRegexp:
|
|
1620
|
+
Description: 'Checks for an array literal interpolated inside a regexp.'
|
|
1621
|
+
Enabled: pending
|
|
1622
|
+
VersionAdded: '1.71'
|
|
1623
|
+
SafeAutoCorrect: false
|
|
1624
|
+
|
|
1619
1625
|
Lint/AssignmentInCondition:
|
|
1620
1626
|
Description: "Don't use assignment in conditions."
|
|
1621
1627
|
StyleGuide: '#safe-assignment-in-condition'
|
|
@@ -1665,6 +1671,11 @@ Lint/ConstantOverwrittenInRescue:
|
|
|
1665
1671
|
Enabled: pending
|
|
1666
1672
|
VersionAdded: '1.31'
|
|
1667
1673
|
|
|
1674
|
+
Lint/ConstantReassignment:
|
|
1675
|
+
Description: 'Checks for constant reassignments.'
|
|
1676
|
+
Enabled: pending
|
|
1677
|
+
VersionAdded: '1.70'
|
|
1678
|
+
|
|
1668
1679
|
Lint/ConstantResolution:
|
|
1669
1680
|
Description: 'Check that constants are fully qualified with `::`.'
|
|
1670
1681
|
Enabled: false
|
|
@@ -2402,6 +2413,12 @@ Lint/ShadowingOuterLocalVariable:
|
|
|
2402
2413
|
Enabled: true
|
|
2403
2414
|
VersionAdded: '0.9'
|
|
2404
2415
|
|
|
2416
|
+
Lint/SharedMutableDefault:
|
|
2417
|
+
Description: 'Checks for mutable literals used as default arguments during Hash initialization.'
|
|
2418
|
+
StyleGuide: '#no-mutable-defaults'
|
|
2419
|
+
Enabled: pending
|
|
2420
|
+
VersionAdded: '1.70'
|
|
2421
|
+
|
|
2405
2422
|
Lint/StructNewOverride:
|
|
2406
2423
|
Description: 'Disallow overriding the `Struct` built-in methods via `Struct.new`.'
|
|
2407
2424
|
Enabled: true
|
|
@@ -3136,13 +3153,14 @@ Style/AccessModifierDeclarations:
|
|
|
3136
3153
|
Description: 'Checks style of how access modifiers are used.'
|
|
3137
3154
|
Enabled: true
|
|
3138
3155
|
VersionAdded: '0.57'
|
|
3139
|
-
VersionChanged: '
|
|
3156
|
+
VersionChanged: '1.70'
|
|
3140
3157
|
EnforcedStyle: group
|
|
3141
3158
|
SupportedStyles:
|
|
3142
3159
|
- inline
|
|
3143
3160
|
- group
|
|
3144
3161
|
AllowModifiersOnSymbols: true
|
|
3145
3162
|
AllowModifiersOnAttrs: true
|
|
3163
|
+
AllowModifiersOnAliasMethod: true
|
|
3146
3164
|
SafeAutoCorrect: false
|
|
3147
3165
|
|
|
3148
3166
|
Style/AccessorGrouping:
|
|
@@ -4051,6 +4069,9 @@ Style/FrozenStringLiteralComment:
|
|
|
4051
4069
|
# exist in a file.
|
|
4052
4070
|
- never
|
|
4053
4071
|
SafeAutoCorrect: false
|
|
4072
|
+
Exclude:
|
|
4073
|
+
# Prevent the Ruby warning: `'frozen_string_literal' is ignored after any tokens` when using Active Admin.
|
|
4074
|
+
- '**/*.arb'
|
|
4054
4075
|
|
|
4055
4076
|
Style/GlobalStdStream:
|
|
4056
4077
|
Description: 'Enforces the use of `$stdout/$stderr/$stdin` instead of `STDOUT/STDERR/STDIN`.'
|
|
@@ -4129,6 +4150,14 @@ Style/HashLikeCase:
|
|
|
4129
4150
|
# to trigger this cop
|
|
4130
4151
|
MinBranchesCount: 3
|
|
4131
4152
|
|
|
4153
|
+
Style/HashSlice:
|
|
4154
|
+
Description: >-
|
|
4155
|
+
Checks for usages of `Hash#reject`, `Hash#select`, and `Hash#filter` methods
|
|
4156
|
+
that can be replaced with `Hash#slice` method.
|
|
4157
|
+
Enabled: pending
|
|
4158
|
+
Safe: false
|
|
4159
|
+
VersionAdded: '1.71'
|
|
4160
|
+
|
|
4132
4161
|
Style/HashSyntax:
|
|
4133
4162
|
Description: >-
|
|
4134
4163
|
Prefer Ruby 1.9 hash syntax { a: 1, b: 2 } over 1.8 syntax
|
|
@@ -4316,6 +4345,11 @@ Style/IpAddresses:
|
|
|
4316
4345
|
- '**/gems.rb'
|
|
4317
4346
|
- '**/*.gemspec'
|
|
4318
4347
|
|
|
4348
|
+
Style/ItAssignment:
|
|
4349
|
+
Description: 'Checks for assignment to `it` inside a block.'
|
|
4350
|
+
Enabled: pending
|
|
4351
|
+
VersionAdded: '1.70'
|
|
4352
|
+
|
|
4319
4353
|
Style/KeywordArgumentsMerging:
|
|
4320
4354
|
Description: >-
|
|
4321
4355
|
When passing an existing hash as keyword arguments, provide additional arguments
|
|
@@ -5059,7 +5093,7 @@ Style/RedundantConstantBase:
|
|
|
5059
5093
|
VersionAdded: '1.40'
|
|
5060
5094
|
|
|
5061
5095
|
Style/RedundantCurrentDirectoryInPath:
|
|
5062
|
-
Description: 'Checks for
|
|
5096
|
+
Description: 'Checks for a redundant current directory in a path given to `require_relative`.'
|
|
5063
5097
|
Enabled: pending
|
|
5064
5098
|
VersionAdded: '1.53'
|
|
5065
5099
|
|
|
@@ -71,11 +71,11 @@ module RuboCop
|
|
|
71
71
|
|
|
72
72
|
warn Rainbow("\n#{pluralize(errors.size, 'error')} occurred:").red
|
|
73
73
|
|
|
74
|
-
errors.each { |error| warn error }
|
|
74
|
+
errors.each { |error| warn Rainbow(error).red }
|
|
75
75
|
|
|
76
|
-
warn <<~WARNING
|
|
76
|
+
warn Rainbow(<<~WARNING.strip).yellow
|
|
77
77
|
Errors are usually caused by RuboCop bugs.
|
|
78
|
-
Please,
|
|
78
|
+
Please, update to the latest RuboCop version if not already in use, and report a bug if the issue still occurs on this version.
|
|
79
79
|
#{bug_tracker_uri}
|
|
80
80
|
Mention the following information in the issue report:
|
|
81
81
|
#{RuboCop::Version.verbose}
|
|
@@ -9,11 +9,31 @@ module RuboCop
|
|
|
9
9
|
class ShowCops < Base
|
|
10
10
|
self.command_name = :show_cops
|
|
11
11
|
|
|
12
|
+
ExactMatcher = Struct.new(:pattern) do
|
|
13
|
+
def match?(name)
|
|
14
|
+
name == pattern
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
WildcardMatcher = Struct.new(:pattern) do
|
|
19
|
+
def match?(name)
|
|
20
|
+
File.fnmatch(pattern, name, File::FNM_PATHNAME)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
12
24
|
def initialize(env)
|
|
13
25
|
super
|
|
14
26
|
|
|
15
27
|
# Load the configs so the require()s are done for custom cops
|
|
16
28
|
@config = @config_store.for(Dir.pwd)
|
|
29
|
+
|
|
30
|
+
@cop_matchers = @options[:show_cops].map do |pattern|
|
|
31
|
+
if pattern.include?('*')
|
|
32
|
+
WildcardMatcher.new(pattern)
|
|
33
|
+
else
|
|
34
|
+
ExactMatcher.new(pattern)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
17
37
|
end
|
|
18
38
|
|
|
19
39
|
def run
|
|
@@ -24,7 +44,7 @@ module RuboCop
|
|
|
24
44
|
|
|
25
45
|
def print_available_cops
|
|
26
46
|
registry = Cop::Registry.global
|
|
27
|
-
show_all = @
|
|
47
|
+
show_all = @cop_matchers.empty?
|
|
28
48
|
|
|
29
49
|
puts "# Available cops (#{registry.length}) + config for #{Dir.pwd}: " if show_all
|
|
30
50
|
|
|
@@ -56,7 +76,9 @@ module RuboCop
|
|
|
56
76
|
|
|
57
77
|
def selected_cops_of_department(cops, department)
|
|
58
78
|
cops_of_department(cops, department).select do |cop|
|
|
59
|
-
@
|
|
79
|
+
@cop_matchers.any? do |matcher|
|
|
80
|
+
matcher.match?(cop.cop_name)
|
|
81
|
+
end
|
|
60
82
|
end
|
|
61
83
|
end
|
|
62
84
|
|
data/lib/rubocop/config.rb
CHANGED
|
@@ -16,6 +16,7 @@ module RuboCop
|
|
|
16
16
|
|
|
17
17
|
CopConfig = Struct.new(:name, :metadata)
|
|
18
18
|
|
|
19
|
+
EMPTY_CONFIG = {}.freeze
|
|
19
20
|
DEFAULT_RAILS_VERSION = 5.0
|
|
20
21
|
attr_reader :loaded_path
|
|
21
22
|
|
|
@@ -80,10 +81,7 @@ module RuboCop
|
|
|
80
81
|
|
|
81
82
|
def make_excludes_absolute
|
|
82
83
|
each_key do |key|
|
|
83
|
-
|
|
84
|
-
next unless self[key]['Exclude']
|
|
85
|
-
|
|
86
|
-
self[key]['Exclude'].map! do |exclude_elem|
|
|
84
|
+
dig(key, 'Exclude')&.map! do |exclude_elem|
|
|
87
85
|
if exclude_elem.is_a?(String) && !absolute?(exclude_elem)
|
|
88
86
|
File.expand_path(File.join(base_dir_for_path_parameters, exclude_elem))
|
|
89
87
|
else
|
|
@@ -123,6 +121,13 @@ module RuboCop
|
|
|
123
121
|
@for_cop[cop]
|
|
124
122
|
end
|
|
125
123
|
|
|
124
|
+
# @return [Config, Hash] for the given cop / cop name.
|
|
125
|
+
# If the given cop is enabled, returns its configuration hash.
|
|
126
|
+
# Otherwise, returns an empty hash.
|
|
127
|
+
def for_enabled_cop(cop)
|
|
128
|
+
cop_enabled?(cop) ? for_cop(cop) : EMPTY_CONFIG
|
|
129
|
+
end
|
|
130
|
+
|
|
126
131
|
# @return [Config] for the given cop merged with that of its department (if any)
|
|
127
132
|
# Note: the 'Enabled' attribute is same as that returned by `for_cop`
|
|
128
133
|
def for_badge(badge)
|
|
@@ -159,6 +164,10 @@ module RuboCop
|
|
|
159
164
|
@for_all_cops ||= self['AllCops'] || {}
|
|
160
165
|
end
|
|
161
166
|
|
|
167
|
+
def cop_enabled?(name)
|
|
168
|
+
!!for_cop(name)['Enabled']
|
|
169
|
+
end
|
|
170
|
+
|
|
162
171
|
def disabled_new_cops?
|
|
163
172
|
for_all_cops['NewCops'] == 'disable'
|
|
164
173
|
end
|
|
@@ -163,14 +163,21 @@ module RuboCop
|
|
|
163
163
|
end
|
|
164
164
|
|
|
165
165
|
def warn_on_duplicate_setting(base_hash, derived_hash, key, **opts)
|
|
166
|
+
# If the file being considered is remote, don't bother checking for duplicates
|
|
167
|
+
return if remote_config?(opts[:file])
|
|
168
|
+
|
|
166
169
|
return unless duplicate_setting?(base_hash, derived_hash, key, opts[:inherited_file])
|
|
167
170
|
|
|
168
171
|
inherit_mode = opts[:inherit_mode]['merge'] || opts[:inherit_mode]['override']
|
|
169
172
|
return if base_hash[key].is_a?(Array) && inherit_mode&.include?(key)
|
|
170
173
|
|
|
171
|
-
puts
|
|
172
|
-
|
|
173
|
-
|
|
174
|
+
puts duplicate_setting_warning(opts, key)
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def duplicate_setting_warning(opts, key)
|
|
178
|
+
"#{PathUtil.smart_path(opts[:file])}: " \
|
|
179
|
+
"#{opts[:cop_name]}:#{key} overrides " \
|
|
180
|
+
"the same parameter in #{opts[:inherited_file]}"
|
|
174
181
|
end
|
|
175
182
|
|
|
176
183
|
def determine_inherit_mode(hash, key)
|
|
@@ -242,6 +249,10 @@ module RuboCop
|
|
|
242
249
|
uri.start_with?('http://', 'https://')
|
|
243
250
|
end
|
|
244
251
|
|
|
252
|
+
def remote_config?(file)
|
|
253
|
+
file.is_a?(RemoteConfig)
|
|
254
|
+
end
|
|
255
|
+
|
|
245
256
|
def handle_disabled_by_default(config, new_default_configuration)
|
|
246
257
|
department_config = config.to_hash.reject { |cop| cop.include?('/') }
|
|
247
258
|
department_config.each do |dept, dept_params|
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
module RuboCop
|
|
4
4
|
# Handles validation of configuration, for example cop names, parameter
|
|
5
5
|
# names, and Ruby versions.
|
|
6
|
+
# rubocop:disable Metrics/ClassLength
|
|
6
7
|
class ConfigValidator
|
|
7
8
|
extend SimpleForwardable
|
|
8
9
|
|
|
@@ -41,8 +42,9 @@ module RuboCop
|
|
|
41
42
|
ConfigLoader.default_configuration.key?(key)
|
|
42
43
|
end
|
|
43
44
|
|
|
44
|
-
|
|
45
|
+
validate_parameter_shape(valid_cop_names)
|
|
45
46
|
|
|
47
|
+
check_obsoletions
|
|
46
48
|
alert_about_unrecognized_cops(invalid_cop_names)
|
|
47
49
|
validate_new_cops_parameter
|
|
48
50
|
validate_parameter_names(valid_cop_names)
|
|
@@ -64,12 +66,6 @@ module RuboCop
|
|
|
64
66
|
target_ruby.version
|
|
65
67
|
end
|
|
66
68
|
|
|
67
|
-
def validate_section_presence(name)
|
|
68
|
-
return unless @config.key?(name) && @config[name].nil?
|
|
69
|
-
|
|
70
|
-
raise ValidationError, "empty section #{name} found in #{smart_loaded_path}"
|
|
71
|
-
end
|
|
72
|
-
|
|
73
69
|
private
|
|
74
70
|
|
|
75
71
|
attr_reader :target_ruby
|
|
@@ -177,9 +173,22 @@ module RuboCop
|
|
|
177
173
|
raise ValidationError, message
|
|
178
174
|
end
|
|
179
175
|
|
|
176
|
+
def validate_parameter_shape(valid_cop_names)
|
|
177
|
+
valid_cop_names.each do |name|
|
|
178
|
+
if @config[name].nil?
|
|
179
|
+
raise ValidationError, "empty section #{name.inspect} found in #{smart_loaded_path}"
|
|
180
|
+
elsif !@config[name].is_a?(Hash)
|
|
181
|
+
raise ValidationError, <<~MESSAGE
|
|
182
|
+
The configuration for #{name.inspect} in #{smart_loaded_path} is not a Hash.
|
|
183
|
+
|
|
184
|
+
Found: #{@config[name].inspect}
|
|
185
|
+
MESSAGE
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
|
|
180
190
|
def validate_parameter_names(valid_cop_names)
|
|
181
191
|
valid_cop_names.each do |name|
|
|
182
|
-
validate_section_presence(name)
|
|
183
192
|
each_invalid_parameter(name) do |param, supported_params|
|
|
184
193
|
warn Rainbow(<<~MESSAGE).yellow
|
|
185
194
|
Warning: #{name} does not support #{param} parameter.
|
|
@@ -277,4 +286,5 @@ module RuboCop
|
|
|
277
286
|
"is supposed to be #{supposed_values} and #{Rainbow(value).yellow} is not."
|
|
278
287
|
end
|
|
279
288
|
end
|
|
289
|
+
# rubocop:enable Metrics/ClassLength
|
|
280
290
|
end
|
data/lib/rubocop/cop/base.rb
CHANGED
|
@@ -261,6 +261,12 @@ module RuboCop
|
|
|
261
261
|
@config.target_ruby_version
|
|
262
262
|
end
|
|
263
263
|
|
|
264
|
+
# Returns a gems locked versions (i.e. from Gemfile.lock or gems.locked)
|
|
265
|
+
# @returns [Gem::Version | nil] The locked gem version, or nil if the gem is not present.
|
|
266
|
+
def target_gem_version(gem_name)
|
|
267
|
+
@config.gem_versions_in_target && @config.gem_versions_in_target[gem_name]
|
|
268
|
+
end
|
|
269
|
+
|
|
264
270
|
def parser_engine
|
|
265
271
|
@config.parser_engine
|
|
266
272
|
end
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module Cop
|
|
5
|
+
module InternalAffairs
|
|
6
|
+
# Use `config.cop_enabled?('Department/CopName')` instead of
|
|
7
|
+
# traversing the config hash.
|
|
8
|
+
#
|
|
9
|
+
# @example
|
|
10
|
+
# # `for_cop(...)['Enabled']
|
|
11
|
+
#
|
|
12
|
+
# # bad
|
|
13
|
+
# config.for_cop('Department/CopName')['Enabled']
|
|
14
|
+
#
|
|
15
|
+
# # good
|
|
16
|
+
# config.cop_enabled?('Department/CopName')
|
|
17
|
+
#
|
|
18
|
+
# @example
|
|
19
|
+
# # when keeping a cop's config in a local and then checking the `Enabled` key
|
|
20
|
+
#
|
|
21
|
+
# # bad
|
|
22
|
+
# cop_config = config.for_cop('Department/CopName')
|
|
23
|
+
# cop_config['Enabled'] && cop_config['Foo']
|
|
24
|
+
#
|
|
25
|
+
# # good
|
|
26
|
+
# config.for_enabled_cop('Department/CopName')['Foo']
|
|
27
|
+
#
|
|
28
|
+
class CopEnabled < Base
|
|
29
|
+
extend AutoCorrector
|
|
30
|
+
|
|
31
|
+
MSG = 'Use `%<replacement>s` instead of `%<source>s`.'
|
|
32
|
+
MSG_HASH = 'Consider replacing uses of `%<hash_name>s` with `config.for_enabled_cop`.'
|
|
33
|
+
|
|
34
|
+
RESTRICT_ON_SEND = [:[]].freeze
|
|
35
|
+
|
|
36
|
+
# @!method for_cop_enabled?(node)
|
|
37
|
+
def_node_matcher :for_cop_enabled?, <<~PATTERN
|
|
38
|
+
(send
|
|
39
|
+
(send
|
|
40
|
+
${(send nil? :config) (ivar :@config)} :for_cop
|
|
41
|
+
$(str _)) :[]
|
|
42
|
+
(str "Enabled"))
|
|
43
|
+
PATTERN
|
|
44
|
+
|
|
45
|
+
# @!method config_enabled_lookup?(node)
|
|
46
|
+
def_node_matcher :config_enabled_lookup?, <<~PATTERN
|
|
47
|
+
(send
|
|
48
|
+
{(lvar $_) (ivar $_) (send nil? $_)} :[]
|
|
49
|
+
(str "Enabled"))
|
|
50
|
+
PATTERN
|
|
51
|
+
|
|
52
|
+
def on_send(node)
|
|
53
|
+
if (config_var, cop_name = for_cop_enabled?(node))
|
|
54
|
+
handle_for_cop(node, config_var, cop_name)
|
|
55
|
+
elsif (config_var = config_enabled_lookup?(node))
|
|
56
|
+
return unless config_var.end_with?('_config')
|
|
57
|
+
|
|
58
|
+
handle_hash(node, config_var)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
private
|
|
63
|
+
|
|
64
|
+
def handle_for_cop(node, config_var, cop_name)
|
|
65
|
+
source = node.source
|
|
66
|
+
quote = cop_name.loc.begin.source
|
|
67
|
+
cop_name = cop_name.value
|
|
68
|
+
|
|
69
|
+
replacement = "#{config_var.source}.cop_enabled?(#{quote}#{cop_name}#{quote})"
|
|
70
|
+
message = format(MSG, source: source, replacement: replacement)
|
|
71
|
+
|
|
72
|
+
add_offense(node, message: message) do |corrector|
|
|
73
|
+
corrector.replace(node, replacement)
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def handle_hash(node, config_var)
|
|
78
|
+
message = format(MSG_HASH, hash_name: config_var)
|
|
79
|
+
|
|
80
|
+
add_offense(node, message: message)
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
@@ -22,7 +22,7 @@ module RuboCop
|
|
|
22
22
|
|
|
23
23
|
def on_send(node)
|
|
24
24
|
return unless (parent = node.parent)
|
|
25
|
-
return unless parent.
|
|
25
|
+
return unless parent.call_type? && parent.method?(:expression)
|
|
26
26
|
return unless parent.receiver.receiver
|
|
27
27
|
|
|
28
28
|
offense = node.loc.selector.join(parent.source_range.end)
|
|
@@ -31,6 +31,7 @@ module RuboCop
|
|
|
31
31
|
corrector.replace(offense, 'source_range')
|
|
32
32
|
end
|
|
33
33
|
end
|
|
34
|
+
alias on_csend on_send
|
|
34
35
|
end
|
|
35
36
|
end
|
|
36
37
|
end
|
|
@@ -27,8 +27,8 @@ module RuboCop
|
|
|
27
27
|
# @!method arguments_first_or_last?(node)
|
|
28
28
|
def_node_matcher :arguments_first_or_last?, <<~PATTERN
|
|
29
29
|
{
|
|
30
|
-
(
|
|
31
|
-
(
|
|
30
|
+
(call (call !nil? :arguments) ${:first :last})
|
|
31
|
+
(call (call !nil? :arguments) :[] (int ${0 -1}))
|
|
32
32
|
}
|
|
33
33
|
PATTERN
|
|
34
34
|
|
|
@@ -47,6 +47,7 @@ module RuboCop
|
|
|
47
47
|
end
|
|
48
48
|
end
|
|
49
49
|
end
|
|
50
|
+
alias on_csend on_send
|
|
50
51
|
end
|
|
51
52
|
end
|
|
52
53
|
end
|
|
@@ -21,16 +21,17 @@ module RuboCop
|
|
|
21
21
|
|
|
22
22
|
# @!method node_type_check(node)
|
|
23
23
|
def_node_matcher :node_type_check, <<~PATTERN
|
|
24
|
-
(send (
|
|
24
|
+
(send (call _ :type) :== (sym $_))
|
|
25
25
|
PATTERN
|
|
26
26
|
|
|
27
27
|
def on_send(node)
|
|
28
|
-
node_type_check(node) do |
|
|
28
|
+
node_type_check(node) do |node_type|
|
|
29
29
|
return unless Parser::Meta::NODE_TYPES.include?(node_type)
|
|
30
30
|
|
|
31
31
|
message = format(MSG, type: node_type)
|
|
32
32
|
add_offense(node, message: message) do |corrector|
|
|
33
|
-
range = node.
|
|
33
|
+
range = node.receiver.loc.selector.join(node.source_range.end)
|
|
34
|
+
|
|
34
35
|
corrector.replace(range, "#{node_type}_type?")
|
|
35
36
|
end
|
|
36
37
|
end
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module Cop
|
|
5
|
+
module InternalAffairs
|
|
6
|
+
# Checks for cops that define `on_send` without define `on_csend`.
|
|
7
|
+
#
|
|
8
|
+
# Although in some cases it can be predetermined that safe navigation
|
|
9
|
+
# will never be used with the code checked by a specific cop, in general
|
|
10
|
+
# it is good practice to handle safe navigation methods if handling any
|
|
11
|
+
# `send` node.
|
|
12
|
+
#
|
|
13
|
+
# NOTE: It is expected to disable this cop for cops that check for method calls
|
|
14
|
+
# on receivers that cannot be nil (`self`, a literal, a constant), and
|
|
15
|
+
# method calls that will never have a receiver (ruby keywords like `raise`,
|
|
16
|
+
# macros like `attr_reader`, DSL methods, etc.), and other checks that wouldn't
|
|
17
|
+
# make sense to support safe navigation.
|
|
18
|
+
#
|
|
19
|
+
# @example
|
|
20
|
+
# # bad
|
|
21
|
+
# class MyCop < RuboCop::Cop:Base
|
|
22
|
+
# def on_send(node)
|
|
23
|
+
# # ...
|
|
24
|
+
# end
|
|
25
|
+
# end
|
|
26
|
+
#
|
|
27
|
+
# # good - explicit method definition
|
|
28
|
+
# class MyCop < RuboCop::Cop:Base
|
|
29
|
+
# def on_send(node)
|
|
30
|
+
# # ...
|
|
31
|
+
# end
|
|
32
|
+
#
|
|
33
|
+
# def on_csend(node)
|
|
34
|
+
# # ...
|
|
35
|
+
# end
|
|
36
|
+
# end
|
|
37
|
+
#
|
|
38
|
+
# # good - alias
|
|
39
|
+
# class MyCop < RuboCop::Cop:Base
|
|
40
|
+
# def on_send(node)
|
|
41
|
+
# # ...
|
|
42
|
+
# end
|
|
43
|
+
# alias on_csend on_send
|
|
44
|
+
# end
|
|
45
|
+
#
|
|
46
|
+
# # good - alias_method
|
|
47
|
+
# class MyCop < RuboCop::Cop:Base
|
|
48
|
+
# def on_send(node)
|
|
49
|
+
# # ...
|
|
50
|
+
# end
|
|
51
|
+
# alias_method :on_csend, :on_send
|
|
52
|
+
# end
|
|
53
|
+
class OnSendWithoutOnCSend < Base
|
|
54
|
+
RESTRICT_ON_SEND = %i[alias_method].freeze
|
|
55
|
+
MSG = 'Cop defines `on_send` but not `on_csend`.'
|
|
56
|
+
|
|
57
|
+
def on_new_investigation
|
|
58
|
+
@on_send_definition = nil
|
|
59
|
+
@on_csend_definition = nil
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def on_investigation_end
|
|
63
|
+
return unless @on_send_definition && !@on_csend_definition
|
|
64
|
+
|
|
65
|
+
add_offense(@on_send_definition)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def on_def(node)
|
|
69
|
+
@on_send_definition = node if node.method?(:on_send)
|
|
70
|
+
@on_csend_definition = node if node.method?(:on_csend)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def on_alias(node)
|
|
74
|
+
@on_send_definition = node if node.new_identifier.value == :on_send
|
|
75
|
+
@on_csend_definition = node if node.new_identifier.value == :on_csend
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def on_send(node) # rubocop:disable InternalAffairs/OnSendWithoutOnCSend
|
|
79
|
+
new_identifier = node.first_argument
|
|
80
|
+
return unless new_identifier.basic_literal?
|
|
81
|
+
|
|
82
|
+
new_identifier = new_identifier.value
|
|
83
|
+
|
|
84
|
+
@on_send_definition = node if new_identifier == :on_send
|
|
85
|
+
@on_csend_definition = node if new_identifier == :on_csend
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
@@ -47,7 +47,7 @@ module RuboCop
|
|
|
47
47
|
# @!method redundant_source_range(node)
|
|
48
48
|
def_node_matcher :redundant_source_range, <<~PATTERN
|
|
49
49
|
{
|
|
50
|
-
(
|
|
50
|
+
(call $(call _ :source_range) :source)
|
|
51
51
|
(send nil? :add_offense $(send _ :source_range) ...)
|
|
52
52
|
(send _ {
|
|
53
53
|
:replace :insert_before :insert_before_multi :insert_after :insert_after_multi
|
|
@@ -67,6 +67,7 @@ module RuboCop
|
|
|
67
67
|
corrector.remove(source_range.loc.dot.join(selector))
|
|
68
68
|
end
|
|
69
69
|
end
|
|
70
|
+
alias on_csend on_send
|
|
70
71
|
end
|
|
71
72
|
end
|
|
72
73
|
end
|
|
@@ -34,8 +34,8 @@ module RuboCop
|
|
|
34
34
|
# @!method single_line_comparison(node)
|
|
35
35
|
def_node_matcher :single_line_comparison, <<~PATTERN
|
|
36
36
|
{
|
|
37
|
-
(send (
|
|
38
|
-
(send (
|
|
37
|
+
(send (call $_receiver {:line :first_line}) {:== :!=} (call _receiver :last_line))
|
|
38
|
+
(send (call $_receiver :last_line) {:== :!=} (call _receiver {:line :first_line}))
|
|
39
39
|
}
|
|
40
40
|
PATTERN
|
|
41
41
|
|
|
@@ -43,7 +43,8 @@ module RuboCop
|
|
|
43
43
|
return unless (receiver = single_line_comparison(node))
|
|
44
44
|
|
|
45
45
|
bang = node.method?(:!=) ? '!' : ''
|
|
46
|
-
|
|
46
|
+
dot = receiver.parent.loc.dot.source
|
|
47
|
+
preferred = "#{bang}#{extract_receiver(receiver)}#{dot}single_line?"
|
|
47
48
|
|
|
48
49
|
add_offense(node, message: format(MSG, preferred: preferred)) do |corrector|
|
|
49
50
|
corrector.replace(node, preferred)
|
|
@@ -53,7 +54,7 @@ module RuboCop
|
|
|
53
54
|
private
|
|
54
55
|
|
|
55
56
|
def extract_receiver(node)
|
|
56
|
-
node = node.receiver if node.
|
|
57
|
+
node = node.receiver if node.call_type? && %i[loc source_range].include?(node.method_name)
|
|
57
58
|
node.source
|
|
58
59
|
end
|
|
59
60
|
end
|