rubocop 1.66.1 → 1.67.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.
Files changed (94) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +15 -6
  4. data/config/internal_affairs.yml +11 -0
  5. data/lib/rubocop/cli/command/auto_generate_config.rb +6 -7
  6. data/lib/rubocop/cli/command/lsp.rb +2 -2
  7. data/lib/rubocop/config_loader_resolver.rb +3 -3
  8. data/lib/rubocop/config_validator.rb +2 -1
  9. data/lib/rubocop/cop/base.rb +6 -2
  10. data/lib/rubocop/cop/bundler/gem_version.rb +1 -0
  11. data/lib/rubocop/cop/cop.rb +8 -0
  12. data/lib/rubocop/cop/correctors/parentheses_corrector.rb +1 -1
  13. data/lib/rubocop/cop/internal_affairs/cop_description.rb +0 -4
  14. data/lib/rubocop/cop/internal_affairs/redundant_message_argument.rb +6 -21
  15. data/lib/rubocop/cop/internal_affairs/redundant_source_range.rb +8 -1
  16. data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +0 -5
  17. data/lib/rubocop/cop/internal_affairs.rb +16 -0
  18. data/lib/rubocop/cop/layout/access_modifier_indentation.rb +5 -1
  19. data/lib/rubocop/cop/layout/def_end_alignment.rb +1 -1
  20. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +1 -1
  21. data/lib/rubocop/cop/layout/first_method_argument_line_break.rb +8 -0
  22. data/lib/rubocop/cop/layout/indentation_width.rb +4 -5
  23. data/lib/rubocop/cop/layout/leading_comment_space.rb +28 -1
  24. data/lib/rubocop/cop/lint/ambiguous_range.rb +4 -1
  25. data/lib/rubocop/cop/lint/big_decimal_new.rb +4 -7
  26. data/lib/rubocop/cop/lint/boolean_symbol.rb +1 -1
  27. data/lib/rubocop/cop/lint/duplicate_set_element.rb +74 -0
  28. data/lib/rubocop/cop/lint/ensure_return.rb +0 -3
  29. data/lib/rubocop/cop/lint/erb_new_arguments.rb +1 -1
  30. data/lib/rubocop/cop/lint/float_comparison.rb +1 -1
  31. data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +10 -4
  32. data/lib/rubocop/cop/lint/it_without_arguments_in_block.rb +5 -14
  33. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +25 -2
  34. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +5 -6
  35. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +1 -1
  36. data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +105 -41
  37. data/lib/rubocop/cop/lint/symbol_conversion.rb +1 -1
  38. data/lib/rubocop/cop/lint/uri_regexp.rb +25 -7
  39. data/lib/rubocop/cop/mixin/percent_array.rb +1 -1
  40. data/lib/rubocop/cop/mixin/statement_modifier.rb +3 -2
  41. data/lib/rubocop/cop/naming/inclusive_language.rb +12 -3
  42. data/lib/rubocop/cop/naming/predicate_name.rb +1 -1
  43. data/lib/rubocop/cop/offense.rb +2 -2
  44. data/lib/rubocop/cop/style/access_modifier_declarations.rb +12 -2
  45. data/lib/rubocop/cop/style/accessor_grouping.rb +10 -2
  46. data/lib/rubocop/cop/style/arguments_forwarding.rb +46 -6
  47. data/lib/rubocop/cop/style/block_delimiters.rb +14 -1
  48. data/lib/rubocop/cop/style/collection_compact.rb +10 -10
  49. data/lib/rubocop/cop/style/combinable_loops.rb +7 -0
  50. data/lib/rubocop/cop/style/commented_keyword.rb +7 -1
  51. data/lib/rubocop/cop/style/conditional_assignment.rb +1 -1
  52. data/lib/rubocop/cop/style/data_inheritance.rb +1 -1
  53. data/lib/rubocop/cop/style/eval_with_location.rb +1 -1
  54. data/lib/rubocop/cop/style/guard_clause.rb +1 -1
  55. data/lib/rubocop/cop/style/hash_each_methods.rb +6 -0
  56. data/lib/rubocop/cop/style/hash_syntax.rb +2 -2
  57. data/lib/rubocop/cop/style/if_inside_else.rb +1 -1
  58. data/lib/rubocop/cop/style/if_with_semicolon.rb +7 -3
  59. data/lib/rubocop/cop/style/lambda.rb +1 -1
  60. data/lib/rubocop/cop/style/map_into_array.rb +53 -7
  61. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +12 -7
  62. data/lib/rubocop/cop/style/multiline_memoization.rb +1 -1
  63. data/lib/rubocop/cop/style/nested_modifier.rb +1 -1
  64. data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +1 -1
  65. data/lib/rubocop/cop/style/one_line_conditional.rb +4 -0
  66. data/lib/rubocop/cop/style/operator_method_call.rb +25 -6
  67. data/lib/rubocop/cop/style/redundant_begin.rb +4 -0
  68. data/lib/rubocop/cop/style/redundant_condition.rb +1 -1
  69. data/lib/rubocop/cop/style/redundant_line_continuation.rb +3 -3
  70. data/lib/rubocop/cop/style/redundant_parentheses.rb +1 -1
  71. data/lib/rubocop/cop/style/require_order.rb +1 -1
  72. data/lib/rubocop/cop/style/rescue_modifier.rb +13 -1
  73. data/lib/rubocop/cop/style/return_nil_in_predicate_method_definition.rb +54 -12
  74. data/lib/rubocop/cop/style/safe_navigation.rb +92 -50
  75. data/lib/rubocop/cop/style/select_by_regexp.rb +9 -6
  76. data/lib/rubocop/cop/style/semicolon.rb +1 -1
  77. data/lib/rubocop/cop/style/struct_inheritance.rb +1 -1
  78. data/lib/rubocop/cop/style/ternary_parentheses.rb +1 -1
  79. data/lib/rubocop/cop/style/trivial_accessors.rb +1 -1
  80. data/lib/rubocop/cop/team.rb +8 -1
  81. data/lib/rubocop/cop/util.rb +1 -1
  82. data/lib/rubocop/cops_documentation_generator.rb +73 -34
  83. data/lib/rubocop/file_finder.rb +9 -4
  84. data/lib/rubocop/lsp/runtime.rb +2 -0
  85. data/lib/rubocop/lsp/server.rb +0 -1
  86. data/lib/rubocop/rspec/expect_offense.rb +1 -0
  87. data/lib/rubocop/runner.rb +3 -0
  88. data/lib/rubocop/server/cache.rb +6 -1
  89. data/lib/rubocop/server/core.rb +1 -0
  90. data/lib/rubocop/target_ruby.rb +12 -12
  91. data/lib/rubocop/version.rb +3 -1
  92. data/lib/rubocop/yaml_duplication_checker.rb +20 -27
  93. data/lib/rubocop.rb +2 -0
  94. metadata +10 -8
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8a10568527197e80492a28c5b524fa524dbce965513daff4f47e260e03b49d98
4
- data.tar.gz: 8ea447437cbd36aa805b3941cf51b07eecc9dc538ed6a4584f09a1335e21cb48
3
+ metadata.gz: d8127fcc41c5b7ffb95a175f82e8a411dfdec0be2b126c7e0868114519d92d01
4
+ data.tar.gz: 2760fa954ef847d049bdd065dec77518c912f5b9050320fe419b9476393b58ea
5
5
  SHA512:
6
- metadata.gz: 1f292c70ffac1cb186e5be899582c4849a29866722c87ab92a60a723dd16fe86fdf12073c8a7190bba197d246eae3b25ba3cdc6b586b28061cef39ac22b3b438
7
- data.tar.gz: 2dbfc28779854fae0d28fd266ba269b92cb0e3b5c26200aa250df02ff9810804b7b1fcc289a43bac1913dc04c79f788487f9351444f7242cbcdad6854a821d69
6
+ metadata.gz: 87ac1904b5fac462a0b76627aac384ddb57493a3620c3ebc929efa9429ee8ad355038caaef2d41192abfcb726d70d85309a442eb93feab8d034544368be32dfd
7
+ data.tar.gz: a011cbaced00ecab1ba1f6ea57983e92c7c872a08c88e450b9aea054bad61cc0f6acae3e1a50c4e4bf545e86ff339000d19995527ff906f0282e2613e7b2638d
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.66', require: false
55
+ gem 'rubocop', '~> 1.67', require: false
56
56
  ```
57
57
 
58
58
  See [our versioning policy](https://docs.rubocop.org/rubocop/versioning.html) for further details.
data/config/default.yml CHANGED
@@ -861,6 +861,7 @@ Layout/FirstMethodArgumentLineBreak:
861
861
  Enabled: false
862
862
  VersionAdded: '0.49'
863
863
  AllowMultilineFinalElement: false
864
+ AllowedMethods: []
864
865
 
865
866
  Layout/FirstMethodParameterLineBreak:
866
867
  Description: >-
@@ -1036,6 +1037,7 @@ Layout/LeadingCommentSpace:
1036
1037
  VersionChanged: '0.73'
1037
1038
  AllowDoxygenCommentStyle: false
1038
1039
  AllowGemfileRubyComment: false
1040
+ AllowRBSInlineAnnotation: false
1039
1041
 
1040
1042
  Layout/LeadingEmptyLines:
1041
1043
  Description: Check for unnecessary blank lines at the beginning of a file.
@@ -1832,6 +1834,11 @@ Lint/DuplicateRescueException:
1832
1834
  Enabled: true
1833
1835
  VersionAdded: '0.89'
1834
1836
 
1837
+ Lint/DuplicateSetElement:
1838
+ Description: 'Checks for duplicate elements in Set.'
1839
+ Enabled: pending
1840
+ VersionAdded: '1.67'
1841
+
1835
1842
  Lint/EachWithObjectArgument:
1836
1843
  Description: 'Check for immutable argument given to each_with_object.'
1837
1844
  Enabled: true
@@ -2327,9 +2334,9 @@ Lint/SafeNavigationChain:
2327
2334
 
2328
2335
  Lint/SafeNavigationConsistency:
2329
2336
  Description: >-
2330
- Check to make sure that if safe navigation is used for a method
2331
- call in an `&&` or `||` condition that safe navigation is used
2332
- for all method calls on that same object.
2337
+ Check to make sure that if safe navigation is used in an `&&` or `||` condition,
2338
+ consistent and appropriate safe navigation, without excess or deficiency,
2339
+ is used for all method calls on the same object.
2333
2340
  Enabled: true
2334
2341
  VersionAdded: '0.55'
2335
2342
  VersionChanged: '0.77'
@@ -4069,7 +4076,7 @@ Style/HashSyntax:
4069
4076
  StyleGuide: '#hash-literals'
4070
4077
  Enabled: true
4071
4078
  VersionAdded: '0.9'
4072
- VersionChanged: '1.24'
4079
+ VersionChanged: '1.67'
4073
4080
  EnforcedStyle: ruby19
4074
4081
  SupportedStyles:
4075
4082
  # checks for 1.9 syntax (e.g. {a: 1}) for all symbol keys
@@ -4081,7 +4088,7 @@ Style/HashSyntax:
4081
4088
  # enforces both ruby19 and no_mixed_keys styles
4082
4089
  - ruby19_no_mixed_keys
4083
4090
  # Force hashes that have a hash value omission
4084
- EnforcedShorthandSyntax: always
4091
+ EnforcedShorthandSyntax: either
4085
4092
  SupportedShorthandSyntax:
4086
4093
  # forces use of the 3.1 syntax (e.g. {foo:}) when the hash key and value are the same.
4087
4094
  - always
@@ -4318,6 +4325,7 @@ Style/MapIntoArray:
4318
4325
  StyleGuide: '#functional-code'
4319
4326
  Enabled: pending
4320
4327
  VersionAdded: '1.63'
4328
+ VersionChanged: '1.67'
4321
4329
  Safe: false
4322
4330
 
4323
4331
  Style/MapToHash:
@@ -5208,6 +5216,7 @@ Style/ReturnNilInPredicateMethodDefinition:
5208
5216
  AllowedMethods: []
5209
5217
  AllowedPatterns: []
5210
5218
  VersionAdded: '1.53'
5219
+ VersionChanged: '1.67'
5211
5220
 
5212
5221
  Style/SafeNavigation:
5213
5222
  Description: >-
@@ -5218,7 +5227,7 @@ Style/SafeNavigation:
5218
5227
  be `nil` or truthy, but never `false`.
5219
5228
  Enabled: true
5220
5229
  VersionAdded: '0.43'
5221
- VersionChanged: '1.27'
5230
+ VersionChanged: '1.67'
5222
5231
  # Safe navigation may cause a statement to start returning `nil` in addition
5223
5232
  # to whatever it used to return.
5224
5233
  ConvertCodeThatCanStartToReturnNil: false
@@ -0,0 +1,11 @@
1
+ # Configuration for InternalAffairs cops. This file will be
2
+ # automatically loaded when `rubocop/cop/internal_affairs` is required.
3
+ # Only do this when developing custom cops or a RuboCop extension.
4
+
5
+ InternalAffairs/CopDescription:
6
+ Include:
7
+ - 'lib/rubocop/cop/**/*.rb'
8
+
9
+ InternalAffairs/UselessMessageAssertion:
10
+ Include:
11
+ - '**/*_spec.rb'
@@ -151,16 +151,15 @@ module RuboCop
151
151
  end
152
152
 
153
153
  def relative_path_to_todo_from_options_config
154
- return AUTO_GENERATED_FILE if !@options[:config] || options_config_in_root?
154
+ return AUTO_GENERATED_FILE unless @options[:config]
155
155
 
156
- base = Pathname.new('.')
157
- config_dir = Pathname.new(File.dirname(@options[:config]))
156
+ base = Pathname.new(Dir.pwd)
157
+ config_dir = Pathname.new(@options[:config]).realpath.dirname
158
158
 
159
- "#{base.relative_path_from(config_dir)}/#{AUTO_GENERATED_FILE}"
160
- end
159
+ # Don't have the path start with `/`
160
+ return AUTO_GENERATED_FILE if config_dir == base
161
161
 
162
- def options_config_in_root?
163
- File.dirname(@options[:config]) == '.'
162
+ "#{base.relative_path_from(config_dir)}/#{AUTO_GENERATED_FILE}"
164
163
  end
165
164
  end
166
165
  end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative '../../lsp/server'
4
-
5
3
  module RuboCop
6
4
  class CLI
7
5
  module Command
@@ -11,6 +9,8 @@ module RuboCop
11
9
  self.command_name = :lsp
12
10
 
13
11
  def run
12
+ # Load on demand, `languge-server-protocol` is heavy to require.
13
+ require_relative '../../lsp/server'
14
14
  RuboCop::LSP::Server.new(@config_store).start
15
15
  end
16
16
  end
@@ -166,7 +166,7 @@ module RuboCop
166
166
  return unless duplicate_setting?(base_hash, derived_hash, key, opts[:inherited_file])
167
167
 
168
168
  inherit_mode = opts[:inherit_mode]['merge'] || opts[:inherit_mode]['override']
169
- return if base_hash[key].is_a?(Array) && inherit_mode && inherit_mode.include?(key)
169
+ return if base_hash[key].is_a?(Array) && inherit_mode&.include?(key)
170
170
 
171
171
  puts "#{PathUtil.smart_path(opts[:file])}: " \
172
172
  "#{opts[:cop_name]}:#{key} overrides " \
@@ -194,11 +194,11 @@ module RuboCop
194
194
  end
195
195
 
196
196
  def should_merge?(mode, key)
197
- mode && mode['merge'] && mode['merge'].include?(key)
197
+ mode && mode['merge']&.include?(key)
198
198
  end
199
199
 
200
200
  def should_override?(mode, key)
201
- mode && mode['override'] && mode['override'].include?(key)
201
+ mode && mode['override']&.include?(key)
202
202
  end
203
203
 
204
204
  def merge_hashes?(base_hash, derived_hash, key)
@@ -7,7 +7,8 @@ module RuboCop
7
7
  extend SimpleForwardable
8
8
 
9
9
  # @api private
10
- COMMON_PARAMS = %w[Exclude Include Severity inherit_mode AutoCorrect StyleGuide Details].freeze
10
+ COMMON_PARAMS = %w[Exclude Include Severity inherit_mode AutoCorrect StyleGuide Details
11
+ Enabled].freeze
11
12
  # @api private
12
13
  INTERNAL_PARAMS = %w[Description StyleGuide
13
14
  VersionAdded VersionChanged VersionRemoved
@@ -322,8 +322,12 @@ module RuboCop
322
322
  # @api private
323
323
  def self.callbacks_needed
324
324
  @callbacks_needed ||= public_instance_methods.select do |m|
325
- m.start_with?(/on_|after_/) &&
326
- !Base.method_defined?(m) # exclude standard "callbacks" like 'on_begin_investigation'
325
+ # OPTIMIZE: Check method existence first to make fewer `start_with?` calls.
326
+ # At the time of writing this comment, this excludes 98 of ~104 methods.
327
+ # `start_with?` with two string arguments instead of a regex is faster
328
+ # in this specific case as well.
329
+ !Base.method_defined?(m) && # exclude standard "callbacks" like 'on_begin_investigation'
330
+ m.start_with?('on_', 'after_')
327
331
  end
328
332
  end
329
333
  # rubocop:enable Layout/ClassStructure
@@ -56,6 +56,7 @@ module RuboCop
56
56
 
57
57
  REQUIRED_MSG = 'Gem version specification is required.'
58
58
  FORBIDDEN_MSG = 'Gem version specification is forbidden.'
59
+ RESTRICT_ON_SEND = %i[gem].freeze
59
60
  VERSION_SPECIFICATION_REGEX = /^\s*[~<>=]*\s*[0-9.]+/.freeze
60
61
 
61
62
  # @!method includes_version_specification?(node)
@@ -22,6 +22,14 @@ module RuboCop
22
22
  end
23
23
  end
24
24
 
25
+ def self.inherited(_subclass)
26
+ super
27
+ warn Rainbow(<<~WARNING).yellow, uplevel: 1
28
+ Inheriting from `RuboCop::Cop::Cop` is deprecated. Use `RuboCop::Cop::Base` instead.
29
+ For more information, see https://docs.rubocop.org/rubocop/v1_upgrade_notes.html.
30
+ WARNING
31
+ end
32
+
25
33
  def self.support_autocorrect?
26
34
  method_defined?(:autocorrect)
27
35
  end
@@ -22,7 +22,7 @@ module RuboCop
22
22
  private
23
23
 
24
24
  def ternary_condition?(node)
25
- node.parent&.if_type? && node.parent&.ternary?
25
+ node.parent&.if_type? && node.parent.ternary?
26
26
  end
27
27
 
28
28
  def next_char_is_question_mark?(node)
@@ -112,10 +112,6 @@ module RuboCop
112
112
  body = comment_body(comment_line)
113
113
  node.source.index(body)
114
114
  end
115
-
116
- def relevant_file?(file)
117
- file.match?(%r{/cop/.*\.rb\z})
118
- end
119
115
  end
120
116
  end
121
117
  end
@@ -11,13 +11,9 @@ module RuboCop
11
11
  #
12
12
  # # bad
13
13
  # add_offense(node, message: MSG)
14
- # add_offense(node, message: message)
15
- # add_offense(node, message: message(node))
16
14
  #
17
15
  # # good
18
16
  # add_offense(node)
19
- # add_offense(node, message: CUSTOM_MSG)
20
- # add_offense(node, message: message(other_node))
21
17
  #
22
18
  class RedundantMessageArgument < Base
23
19
  include RangeHelp
@@ -28,22 +24,21 @@ module RuboCop
28
24
 
29
25
  # @!method node_type_check(node)
30
26
  def_node_matcher :node_type_check, <<~PATTERN
31
- (send nil? :add_offense $_node $hash)
27
+ (send nil? :add_offense _node $hash)
32
28
  PATTERN
33
29
 
34
30
  # @!method redundant_message_argument(node)
35
31
  def_node_matcher :redundant_message_argument, <<~PATTERN
36
32
  (pair
37
33
  (sym :message)
38
- ${(const nil? :MSG) (send nil? :message) (send nil? :message _)})
34
+ $(const nil? :MSG))
39
35
  PATTERN
40
36
 
41
- # @!method message_method_call(node)
42
- def_node_matcher :message_method_call, '(send nil? :message $_node)'
43
-
44
37
  def on_send(node)
45
- node_type_check(node) do |node_arg, kwargs|
46
- find_offending_argument(node_arg, kwargs) do |pair|
38
+ return unless (kwargs = node_type_check(node))
39
+
40
+ kwargs.pairs.each do |pair|
41
+ redundant_message_argument(pair) do
47
42
  add_offense(pair) do |corrector|
48
43
  range = offending_range(pair)
49
44
 
@@ -60,16 +55,6 @@ module RuboCop
60
55
 
61
56
  range_with_surrounding_comma(with_space, :left)
62
57
  end
63
-
64
- def find_offending_argument(searched_node, kwargs)
65
- kwargs.pairs.each do |pair|
66
- redundant_message_argument(pair) do |message_argument|
67
- node = message_method_call(message_argument)
68
-
69
- yield pair if !node || node == searched_node
70
- end
71
- end
72
- end
73
58
  end
74
59
  end
75
60
  end
@@ -14,6 +14,12 @@ module RuboCop
14
14
  # node.source
15
15
  #
16
16
  # # bad
17
+ # add_offense(node.source_range)
18
+ #
19
+ # # good
20
+ # add_offense(node)
21
+ #
22
+ # # bad
17
23
  # add_offense(node) { |corrector| corrector.replace(node.source_range, prefer) }
18
24
  # add_offense(node) { |corrector| corrector.insert_before(node.source_range, prefer) }
19
25
  # add_offense(node) { |corrector| corrector.insert_before_multi(node.source_range, prefer) }
@@ -34,7 +40,7 @@ module RuboCop
34
40
 
35
41
  MSG = 'Remove the redundant `source_range`.'
36
42
  RESTRICT_ON_SEND = %i[
37
- source
43
+ source add_offense
38
44
  replace remove insert_before insert_before_multi insert_after insert_after_multi swap
39
45
  ].freeze
40
46
 
@@ -42,6 +48,7 @@ module RuboCop
42
48
  def_node_matcher :redundant_source_range, <<~PATTERN
43
49
  {
44
50
  (send $(send _ :source_range) :source)
51
+ (send nil? :add_offense $(send _ :source_range) ...)
45
52
  (send _ {
46
53
  :replace :insert_before :insert_before_multi :insert_after :insert_after_multi
47
54
  } $(send _ :source_range) _)
@@ -43,11 +43,6 @@ module RuboCop
43
43
  node.ancestors.any? { |ancestor| rspec_expectation_on_msg?(ancestor) }
44
44
  end
45
45
  end
46
-
47
- # Only process spec files
48
- def relevant_file?(file)
49
- file.end_with?('_spec.rb')
50
- end
51
46
  end
52
47
  end
53
48
  end
@@ -31,3 +31,19 @@ require_relative 'internal_affairs/style_detected_api_use'
31
31
  require_relative 'internal_affairs/undefined_config'
32
32
  require_relative 'internal_affairs/useless_message_assertion'
33
33
  require_relative 'internal_affairs/useless_restrict_on_send'
34
+
35
+ module RuboCop
36
+ # Patch in the InternalAffairs specific config values
37
+ module InternalAffairs
38
+ def self.inject!
39
+ path = File.join(ConfigLoader::RUBOCOP_HOME, 'config', 'internal_affairs.yml')
40
+ hash = ConfigLoader.load_yaml_configuration(path)
41
+ config = Config.new(hash, path)
42
+ puts "configuration from #{path}" if ConfigLoader.debug?
43
+ config = ConfigLoader.merge_with_default(config, path)
44
+ ConfigLoader.instance_variable_set(:@default_configuration, config)
45
+ end
46
+ end
47
+ end
48
+
49
+ RuboCop::InternalAffairs.inject!
@@ -59,7 +59,11 @@ module RuboCop
59
59
  modifiers = body.each_child_node(:send).select(&:bare_access_modifier?)
60
60
  end_range = node.loc.end
61
61
 
62
- modifiers.each { |modifier| check_modifier(modifier, end_range) }
62
+ modifiers.each do |modifier|
63
+ next if same_line?(node, modifier)
64
+
65
+ check_modifier(modifier, end_range)
66
+ end
63
67
  end
64
68
 
65
69
  def check_modifier(send_node, end_range)
@@ -61,7 +61,7 @@ module RuboCop
61
61
  private
62
62
 
63
63
  def autocorrect(corrector, node)
64
- if style == :start_of_line && node.parent && node.parent.send_type?
64
+ if style == :start_of_line && node.parent&.send_type?
65
65
  AlignmentCorrector.align_end(corrector, processed_source, node, node.parent)
66
66
  else
67
67
  AlignmentCorrector.align_end(corrector, processed_source, node, node)
@@ -135,7 +135,7 @@ module RuboCop
135
135
 
136
136
  parent = next_sibling.parent
137
137
 
138
- parent&.if_type? && parent&.else?
138
+ parent&.if_type? && parent.else?
139
139
  end
140
140
 
141
141
  def next_sibling_empty_or_guard_clause?(node)
@@ -63,13 +63,21 @@ module RuboCop
63
63
  # }
64
64
  # )
65
65
  #
66
+ # @example AllowedMethods: ['some_method']
67
+ #
68
+ # # good
69
+ # some_method(foo, bar,
70
+ # baz)
66
71
  class FirstMethodArgumentLineBreak < Base
67
72
  include FirstElementLineBreak
73
+ include AllowedMethods
68
74
  extend AutoCorrector
69
75
 
70
76
  MSG = 'Add a line break before the first argument of a multi-line method argument list.'
71
77
 
72
78
  def on_send(node)
79
+ return if allowed_method?(node.method_name)
80
+
73
81
  args = node.arguments.dup
74
82
 
75
83
  # If there is a trailing hash arg without explicit braces, like this:
@@ -3,13 +3,12 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Layout
6
- # Checks for indentation that doesn't use the specified number
7
- # of spaces.
6
+ # Checks for indentation that doesn't use the specified number of spaces.
7
+ # The indentation width can be configured using the `Width` setting. The default width is 2.
8
8
  #
9
- # See also the IndentationConsistency cop which is the companion to this
10
- # one.
9
+ # See also the `Layout/IndentationConsistency` cop which is the companion to this one.
11
10
  #
12
- # @example
11
+ # @example Width: 2 (default)
13
12
  # # bad
14
13
  # class A
15
14
  # def test
@@ -49,18 +49,37 @@ module RuboCop
49
49
  # #ruby=2.7.0
50
50
  # #ruby-gemset=myproject
51
51
  #
52
+ # @example AllowRBSInlineAnnotation: false (default)
53
+ #
54
+ # # bad
55
+ #
56
+ # include Enumerable #[Integer]
57
+ #
58
+ # attr_reader :name #: String
59
+ # attr_reader :age #: Integer?
60
+ #
61
+ # @example AllowRBSInlineAnnotation: true
62
+ #
63
+ # # good
64
+ #
65
+ # include Enumerable #[Integer]
66
+ #
67
+ # attr_reader :name #: String
68
+ # attr_reader :age #: Integer?
69
+ #
52
70
  class LeadingCommentSpace < Base
53
71
  include RangeHelp
54
72
  extend AutoCorrector
55
73
 
56
74
  MSG = 'Missing space after `#`.'
57
75
 
58
- def on_new_investigation
76
+ def on_new_investigation # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
59
77
  processed_source.comments.each do |comment|
60
78
  next unless /\A(?!#\+\+|#--)(#+[^#\s=])/.match?(comment.text)
61
79
  next if comment.loc.line == 1 && allowed_on_first_line?(comment)
62
80
  next if doxygen_comment_style?(comment)
63
81
  next if gemfile_ruby_comment?(comment)
82
+ next if rbs_inline_annotation?(comment)
64
83
 
65
84
  add_offense(comment) do |corrector|
66
85
  expr = comment.source_range
@@ -115,6 +134,14 @@ module RuboCop
115
134
  def gemfile_ruby_comment?(comment)
116
135
  allow_gemfile_ruby_comment? && ruby_comment_in_gemfile?(comment)
117
136
  end
137
+
138
+ def allow_rbs_inline_annotation?
139
+ cop_config['AllowRBSInlineAnnotation']
140
+ end
141
+
142
+ def rbs_inline_annotation?(comment)
143
+ allow_rbs_inline_annotation? && comment.text.start_with?(/#:|#\[.+\]/)
144
+ end
118
145
  end
119
146
  end
120
147
  end
@@ -57,6 +57,7 @@ module RuboCop
57
57
  # # good
58
58
  # (a.foo)..(b.bar)
59
59
  class AmbiguousRange < Base
60
+ include RationalLiteral
60
61
  extend AutoCorrector
61
62
 
62
63
  MSG = 'Wrap complex range boundaries with parentheses to avoid ambiguity.'
@@ -79,12 +80,14 @@ module RuboCop
79
80
  yield range.end if range.end
80
81
  end
81
82
 
83
+ # rubocop:disable Metrics/CyclomaticComplexity
82
84
  def acceptable?(node)
83
85
  node.begin_type? ||
84
- node.literal? ||
86
+ node.literal? || rational_literal?(node) ||
85
87
  node.variable? || node.const_type? || node.self_type? ||
86
88
  (node.call_type? && acceptable_call?(node))
87
89
  end
90
+ # rubocop:enable Metrics/CyclomaticComplexity
88
91
 
89
92
  def acceptable_call?(node)
90
93
  return true if node.unary_operation?
@@ -17,8 +17,7 @@ module RuboCop
17
17
  class BigDecimalNew < Base
18
18
  extend AutoCorrector
19
19
 
20
- MSG = '`%<double_colon>sBigDecimal.new()` is deprecated. ' \
21
- 'Use `%<double_colon>sBigDecimal()` instead.'
20
+ MSG = '`BigDecimal.new()` is deprecated. Use `BigDecimal()` instead.'
22
21
  RESTRICT_ON_SEND = %i[new].freeze
23
22
 
24
23
  # @!method big_decimal_new(node)
@@ -28,13 +27,11 @@ module RuboCop
28
27
  PATTERN
29
28
 
30
29
  def on_send(node)
31
- big_decimal_new(node) do |captured_value|
32
- double_colon = captured_value ? '::' : ''
33
- message = format(MSG, double_colon: double_colon)
34
-
35
- add_offense(node.loc.selector, message: message) do |corrector|
30
+ big_decimal_new(node) do |cbase|
31
+ add_offense(node.loc.selector) do |corrector|
36
32
  corrector.remove(node.loc.selector)
37
33
  corrector.remove(node.loc.dot)
34
+ corrector.remove(cbase) if cbase
38
35
  end
39
36
  end
40
37
  end
@@ -36,7 +36,7 @@ module RuboCop
36
36
  return unless boolean_symbol?(node)
37
37
 
38
38
  parent = node.parent
39
- return if parent&.array_type? && parent&.percent_literal?(:symbol)
39
+ return if parent&.array_type? && parent.percent_literal?(:symbol)
40
40
 
41
41
  add_offense(node, message: format(MSG, boolean: node.value)) do |corrector|
42
42
  autocorrect(corrector, node)
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Lint
6
+ # Checks for duplicate literal, constant, or variable elements in Set.
7
+ #
8
+ # @example
9
+ #
10
+ # # bad
11
+ # Set[:foo, :bar, :foo]
12
+ #
13
+ # # good
14
+ # Set[:foo, :bar]
15
+ #
16
+ # # bad
17
+ # Set.new([:foo, :bar, :foo])
18
+ #
19
+ # # good
20
+ # Set.new([:foo, :bar])
21
+ #
22
+ # # bad
23
+ # [:foo, :bar, :foo].to_set
24
+ #
25
+ # # good
26
+ # [:foo, :bar].to_set
27
+ #
28
+ class DuplicateSetElement < Base
29
+ extend AutoCorrector
30
+
31
+ MSG = 'Remove the duplicate element in Set.'
32
+ RESTRICT_ON_SEND = %i[\[\] new to_set].freeze
33
+
34
+ # @!method set_init_elements(node)
35
+ def_node_matcher :set_init_elements, <<~PATTERN
36
+ {
37
+ (send (const {nil? cbase} :Set) :[] $...)
38
+ (send (const {nil? cbase} :Set) :new (array $...))
39
+ (call (array $...) :to_set)
40
+ }
41
+ PATTERN
42
+
43
+ def on_send(node)
44
+ return unless (set_elements = set_init_elements(node))
45
+
46
+ seen_elements = Set[]
47
+
48
+ set_elements.each_with_index do |set_element, index|
49
+ # NOTE: Skip due to the possibility of corner cases where Set elements
50
+ # may have changing return values if they are not literals, constants, or variables.
51
+ next if !set_element.literal? && !set_element.const_type? && !set_element.variable?
52
+
53
+ if seen_elements.include?(set_element)
54
+ register_offense(set_element, set_elements[index - 1])
55
+ else
56
+ seen_elements << set_element
57
+ end
58
+ end
59
+ end
60
+ alias on_csend on_send
61
+
62
+ private
63
+
64
+ def register_offense(current_element, prev_element)
65
+ add_offense(current_element) do |corrector|
66
+ range = prev_element.source_range.end.join(current_element.source_range.end)
67
+
68
+ corrector.remove(range)
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -40,9 +40,6 @@ module RuboCop
40
40
  # cleanup
41
41
  # end
42
42
  class EnsureReturn < Base
43
- extend AutoCorrector
44
- include RangeHelp
45
-
46
43
  MSG = 'Do not return from an `ensure` block.'
47
44
 
48
45
  def on_ensure(node)