rubocop 1.81.7 → 1.82.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +21 -5
  4. data/config/obsoletion.yml +4 -0
  5. data/lib/rubocop/cli.rb +2 -1
  6. data/lib/rubocop/comment_config.rb +62 -17
  7. data/lib/rubocop/config_loader.rb +2 -1
  8. data/lib/rubocop/config_loader_resolver.rb +2 -2
  9. data/lib/rubocop/cop/autocorrect_logic.rb +4 -0
  10. data/lib/rubocop/cop/bundler/ordered_gems.rb +1 -2
  11. data/lib/rubocop/cop/correctors/alignment_corrector.rb +1 -3
  12. data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +1 -2
  13. data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +10 -5
  14. data/lib/rubocop/cop/internal_affairs/location_exists.rb +28 -2
  15. data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_processor.rb +1 -1
  16. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +3 -0
  17. data/lib/rubocop/cop/layout/end_alignment.rb +4 -0
  18. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +2 -2
  19. data/lib/rubocop/cop/layout/heredoc_indentation.rb +1 -4
  20. data/lib/rubocop/cop/layout/indentation_style.rb +1 -1
  21. data/lib/rubocop/cop/layout/indentation_width.rb +12 -1
  22. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +1 -1
  23. data/lib/rubocop/cop/layout/line_length.rb +8 -4
  24. data/lib/rubocop/cop/layout/multiline_block_layout.rb +2 -0
  25. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +5 -1
  26. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +5 -3
  27. data/lib/rubocop/cop/layout/space_after_comma.rb +2 -10
  28. data/lib/rubocop/cop/layout/space_after_semicolon.rb +1 -1
  29. data/lib/rubocop/cop/layout/space_around_keyword.rb +1 -1
  30. data/lib/rubocop/cop/lint/circular_argument_reference.rb +47 -3
  31. data/lib/rubocop/cop/lint/cop_directive_syntax.rb +1 -1
  32. data/lib/rubocop/cop/lint/duplicate_match_pattern.rb +4 -4
  33. data/lib/rubocop/cop/lint/else_layout.rb +19 -0
  34. data/lib/rubocop/cop/lint/literal_as_condition.rb +4 -0
  35. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +1 -1
  36. data/lib/rubocop/cop/lint/no_return_in_begin_end_blocks.rb +4 -0
  37. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +23 -9
  38. data/lib/rubocop/cop/lint/redundant_require_statement.rb +4 -2
  39. data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +7 -1
  40. data/lib/rubocop/cop/lint/self_assignment.rb +9 -1
  41. data/lib/rubocop/cop/lint/unreachable_code.rb +5 -3
  42. data/lib/rubocop/cop/lint/useless_assignment.rb +44 -16
  43. data/lib/rubocop/cop/lint/useless_or.rb +15 -2
  44. data/lib/rubocop/cop/lint/utils/nil_receiver_checker.rb +1 -1
  45. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +4 -3
  46. data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +2 -4
  47. data/lib/rubocop/cop/mixin/code_length.rb +1 -1
  48. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +1 -1
  49. data/lib/rubocop/cop/mixin/line_length_help.rb +21 -2
  50. data/lib/rubocop/cop/mixin/method_complexity.rb +1 -1
  51. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +1 -1
  52. data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +1 -1
  53. data/lib/rubocop/cop/mixin/space_after_punctuation.rb +5 -4
  54. data/lib/rubocop/cop/mixin/statement_modifier.rb +0 -6
  55. data/lib/rubocop/cop/mixin/trailing_comma.rb +7 -4
  56. data/lib/rubocop/cop/naming/method_name.rb +1 -1
  57. data/lib/rubocop/cop/style/bare_percent_literals.rb +1 -2
  58. data/lib/rubocop/cop/style/case_equality.rb +11 -13
  59. data/lib/rubocop/cop/style/class_and_module_children.rb +1 -0
  60. data/lib/rubocop/cop/style/conditional_assignment.rb +1 -11
  61. data/lib/rubocop/cop/style/constant_visibility.rb +3 -3
  62. data/lib/rubocop/cop/style/empty_method.rb +0 -6
  63. data/lib/rubocop/cop/style/endless_method.rb +2 -2
  64. data/lib/rubocop/cop/style/guard_clause.rb +0 -11
  65. data/lib/rubocop/cop/style/if_unless_modifier.rb +3 -3
  66. data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +12 -1
  67. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +17 -4
  68. data/lib/rubocop/cop/style/module_member_existence_check.rb +74 -0
  69. data/lib/rubocop/cop/style/multiline_method_signature.rb +2 -4
  70. data/lib/rubocop/cop/style/operator_method_call.rb +11 -2
  71. data/lib/rubocop/cop/style/parallel_assignment.rb +2 -2
  72. data/lib/rubocop/cop/style/redundant_argument.rb +2 -0
  73. data/lib/rubocop/cop/style/redundant_percent_q.rb +1 -2
  74. data/lib/rubocop/cop/style/redundant_regexp_argument.rb +5 -0
  75. data/lib/rubocop/cop/style/redundant_sort.rb +7 -7
  76. data/lib/rubocop/cop/style/super_arguments.rb +2 -2
  77. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +11 -11
  78. data/lib/rubocop/cop/util.rb +2 -3
  79. data/lib/rubocop/directive_comment.rb +46 -3
  80. data/lib/rubocop/formatter/disabled_config_formatter.rb +1 -0
  81. data/lib/rubocop/lsp/diagnostic.rb +12 -17
  82. data/lib/rubocop/lsp/routes.rb +9 -36
  83. data/lib/rubocop/lsp/runtime.rb +2 -2
  84. data/lib/rubocop/lsp/server.rb +2 -2
  85. data/lib/rubocop/magic_comment.rb +20 -0
  86. data/lib/rubocop/rake_task.rb +1 -1
  87. data/lib/rubocop/remote_config.rb +7 -8
  88. data/lib/rubocop/result_cache.rb +38 -27
  89. data/lib/rubocop/rspec/shared_contexts.rb +2 -2
  90. data/lib/rubocop/rspec/support.rb +1 -1
  91. data/lib/rubocop/runner.rb +4 -0
  92. data/lib/rubocop/target_ruby.rb +1 -1
  93. data/lib/rubocop/version.rb +1 -1
  94. data/lib/rubocop.rb +1 -0
  95. metadata +8 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8acfafa4ed4b94c367e6ef95c84d2d02f01222a1e8a813790948977476f34456
4
- data.tar.gz: 0d2ad56c4a81da58046a098351606bfb8314f09f9e5f946ad1dd825aa70fe0f7
3
+ metadata.gz: 9dfdd0a2943006435a98725498ab85032b82d1cff547cd0bed007a250e56aca4
4
+ data.tar.gz: c6a9e601a1e7858282d835dc00cd0f065ab3bc43de633988877dae6422f85f71
5
5
  SHA512:
6
- metadata.gz: ae4edea22ca7511df39ec99591df3d537bfd3fa8974d5bb461d2b1c674b48f15296f22c81b1cd9329719a68b0d3f8d36442eaa5742cbf8e0974c6e3e2e56e29c
7
- data.tar.gz: ffce467cec50d2ed0ef7b312a15dd17e9b7fd1622b70528d12f0cfe16056ae3b5111f2d360b4e855ea5811befd092a306ff56ad091b89a6050f3354f3db205a4
6
+ metadata.gz: e19cc58194cf953813d3e3bf0d3bfa7d976f30127008ba84473b08cdcba188a4f73ac102baea188dfa463723b15fc768a3b7152306d5fcb5a5b7b7265e031ad2
7
+ data.tar.gz: 26ed5927b0b375947c553a46434c6a58a63022c928b84b03ff1b44a8a74eee6c8cb29342262df28fcca223e194257d7e9fe7a06fb422d42e0805287380830743
data/README.md CHANGED
@@ -51,7 +51,7 @@ To prevent an unwanted RuboCop update you might want to use a conservative versi
51
51
  in your `Gemfile`:
52
52
 
53
53
  ```rb
54
- gem 'rubocop', '~> 1.81', require: false
54
+ gem 'rubocop', '~> 1.82', require: false
55
55
  ```
56
56
 
57
57
  See [our versioning policy](https://docs.rubocop.org/rubocop/versioning.html) for further details.
data/config/default.yml CHANGED
@@ -1102,7 +1102,7 @@ Layout/LineLength:
1102
1102
  StyleGuide: '#max-line-length'
1103
1103
  Enabled: true
1104
1104
  VersionAdded: '0.25'
1105
- VersionChanged: '1.69'
1105
+ VersionChanged: '1.82'
1106
1106
  Max: 120
1107
1107
  AllowHeredoc: true
1108
1108
  # To make it possible to copy or click on URIs in the code, we allow lines
@@ -1112,9 +1112,12 @@ Layout/LineLength:
1112
1112
  URISchemes:
1113
1113
  - http
1114
1114
  - https
1115
- # The IgnoreCopDirectives option causes the LineLength rule to ignore cop
1115
+ # The AllowRBSInlineAnnotation option makes LineLength allow RBS::Inline annotations
1116
+ # such as `#: (?date: Date) -> Foo` when calculating line length.
1117
+ AllowRBSInlineAnnotation: false
1118
+ # The AllowCopDirectives option causes the LineLength rule to ignore cop
1116
1119
  # directives like '# rubocop: enable ...' when calculating a line's length.
1117
- IgnoreCopDirectives: true
1120
+ AllowCopDirectives: true
1118
1121
  # The AllowedPatterns option is a list of !ruby/regexp and/or string
1119
1122
  # elements. Strings will be converted to Regexp objects. A line that matches
1120
1123
  # any regular expression listed in this option will be ignored by LineLength.
@@ -2669,7 +2672,10 @@ Lint/UselessNumericOperation:
2669
2672
  Lint/UselessOr:
2670
2673
  Description: 'Checks for useless OR expressions.'
2671
2674
  Enabled: pending
2675
+ SafeAutoCorrect: false
2676
+ AutoCorrect: contextual
2672
2677
  VersionAdded: '1.76'
2678
+ VersionChanged: '1.82'
2673
2679
 
2674
2680
  Lint/UselessRescue:
2675
2681
  Description: 'Checks for useless `rescue`s.'
@@ -3281,7 +3287,7 @@ Style/Alias:
3281
3287
 
3282
3288
  Style/AmbiguousEndlessMethodDefinition:
3283
3289
  Description: 'Checks for endless methods inside operators of lower precedence.'
3284
- StyleGuide: '#ambiguous-endless-method-defintions'
3290
+ StyleGuide: '#ambiguous-endless-method-definitions'
3285
3291
  Enabled: pending
3286
3292
  VersionAdded: '1.68'
3287
3293
 
@@ -3525,9 +3531,11 @@ Style/BlockDelimiters:
3525
3531
  BracesRequiredMethods: []
3526
3532
 
3527
3533
  Style/CaseEquality:
3528
- Description: 'Avoid explicit use of the case equality operator(===).'
3534
+ Description: 'Avoid explicit use of the case equality operator (`===`).'
3529
3535
  StyleGuide: '#no-case-equality'
3530
3536
  Enabled: true
3537
+ References:
3538
+ - 'https://docs.rubocop.org/rubocop-performance/cops_performance.html#performanceregexpmatch'
3531
3539
  VersionAdded: '0.9'
3532
3540
  VersionChanged: '0.89'
3533
3541
  # If `AllowOnConstant` option is enabled, the cop will ignore violations when the receiver of
@@ -4625,6 +4633,7 @@ Style/MethodCallWithArgsParentheses:
4625
4633
  AllowedMethods: []
4626
4634
  AllowedPatterns: []
4627
4635
  IncludedMacros: []
4636
+ IncludedMacroPatterns: []
4628
4637
  AllowParenthesesInMultilineCall: false
4629
4638
  AllowParenthesesInChaining: false
4630
4639
  AllowParenthesesInCamelCaseMethod: false
@@ -4735,6 +4744,11 @@ Style/ModuleFunction:
4735
4744
  Autocorrect: false
4736
4745
  SafeAutoCorrect: false
4737
4746
 
4747
+ Style/ModuleMemberExistenceCheck:
4748
+ Description: 'Checks for usage of `Module` methods returning arrays that can be replaced with equivalent predicates.'
4749
+ Enabled: pending
4750
+ VersionAdded: '1.82'
4751
+
4738
4752
  Style/MultilineBlockChain:
4739
4753
  Description: 'Avoid multi-line chains of blocks.'
4740
4754
  StyleGuide: '#single-line-blocks'
@@ -5222,6 +5236,8 @@ Style/RedundantArgument:
5222
5236
  exit: true
5223
5237
  # Kernel.#exit!
5224
5238
  exit!: false
5239
+ # String#to_i
5240
+ to_i: 10
5225
5241
  # String#split
5226
5242
  split: ' '
5227
5243
  # String#chomp
@@ -145,6 +145,10 @@ changed_parameters:
145
145
  - cops: Layout/CaseIndentation
146
146
  parameters: IndentWhenRelativeTo
147
147
  alternative: EnforcedStyle
148
+ - cops: Layout/LineLength
149
+ parameters: IgnoreCopDirectives
150
+ alternative: AllowCopDirectives
151
+ severity: warning
148
152
  - cops:
149
153
  - Lint/BlockAlignment
150
154
  - Layout/BlockAlignment
data/lib/rubocop/cli.rb CHANGED
@@ -66,7 +66,7 @@ module RuboCop
66
66
  STATUS_INTERRUPTED
67
67
  rescue Finished
68
68
  STATUS_SUCCESS
69
- rescue OptionParser::InvalidOption => e
69
+ rescue OptionParser::ParseError => e
70
70
  warn e.message
71
71
  warn 'For usage information, use --help'
72
72
  STATUS_ERROR
@@ -183,6 +183,7 @@ module RuboCop
183
183
  ConfigLoader.enable_pending_cops = @options[:enable_pending_cops]
184
184
  ConfigLoader.ignore_parent_exclusion = @options[:ignore_parent_exclusion]
185
185
  ConfigLoader.ignore_unrecognized_cops = @options[:ignore_unrecognized_cops]
186
+ ConfigLoader.cache_root = ResultCache.cache_root(@config_store, @options[:cache_root])
186
187
  end
187
188
 
188
189
  def set_options_to_pending_cops_reporter
@@ -34,6 +34,7 @@ module RuboCop
34
34
  def initialize(processed_source)
35
35
  @processed_source = processed_source
36
36
  @no_directives = !processed_source.raw_source.include?('rubocop')
37
+ @stack = []
37
38
  end
38
39
 
39
40
  def cop_enabled_at_line?(cop, line_number)
@@ -93,16 +94,23 @@ module RuboCop
93
94
  end
94
95
  end
95
96
 
96
- def analyze # rubocop:todo Metrics/AbcSize
97
+ def analyze # rubocop:todo Metrics/AbcSize, Metrics/MethodLength
97
98
  return {} if @no_directives
98
99
 
99
100
  analyses = Hash.new { |hash, key| hash[key] = CopAnalysis.new([], nil) }
100
101
  inject_disabled_cops_directives(analyses)
101
102
 
102
103
  each_directive do |directive|
103
- directive.cop_names.each do |cop_name|
104
- cop_name = qualified_cop_name(cop_name)
105
- analyses[cop_name] = analyze_cop(analyses[cop_name], directive)
104
+ if directive.push?
105
+ @stack.push(snapshot_analyses(analyses))
106
+ apply_push_args(analyses, directive)
107
+ elsif directive.pop?
108
+ pop_state(analyses, directive.line_number) if @stack.any?
109
+ else
110
+ directive.cop_names.each do |cop_name|
111
+ cop_name = qualified_cop_name(cop_name)
112
+ analyses[cop_name] = analyze_cop(analyses[cop_name], directive)
113
+ end
106
114
  end
107
115
  end
108
116
 
@@ -112,6 +120,51 @@ module RuboCop
112
120
  end
113
121
  end
114
122
 
123
+ def snapshot_analyses(analyses)
124
+ analyses.transform_values { |a| CopAnalysis.new(a.line_ranges.dup, a.start_line_number) }
125
+ end
126
+
127
+ def pop_state(analyses, pop_line)
128
+ analyses.each do |cop_name, analysis|
129
+ next unless analysis.start_line_number
130
+
131
+ analyses[cop_name] = CopAnalysis.new(
132
+ analysis.line_ranges + [analysis.start_line_number...pop_line], nil
133
+ )
134
+ end
135
+
136
+ @stack.pop.each do |cop_name, saved_analysis|
137
+ current = analyses[cop_name]
138
+ new_start = saved_analysis.start_line_number ? pop_line : nil
139
+ analyses[cop_name] = CopAnalysis.new(current.line_ranges, new_start)
140
+ end
141
+ end
142
+
143
+ def apply_push_args(analyses, directive)
144
+ directive.push_args.each do |operation, cop_names|
145
+ cop_names.each do |cop_name|
146
+ apply_cop_operation(analyses, operation, qualified_cop_name(cop_name),
147
+ directive.line_number)
148
+ end
149
+ end
150
+ end
151
+
152
+ def apply_cop_operation(analyses, operation, cop_name, line)
153
+ analysis = analyses[cop_name]
154
+ start_line = analysis.start_line_number
155
+
156
+ case operation
157
+ when '+' # Enable cop
158
+ return unless start_line
159
+
160
+ analyses[cop_name] = CopAnalysis.new(analysis.line_ranges + [start_line..line], nil)
161
+ when '-' # Disable cop
162
+ return if start_line
163
+
164
+ analyses[cop_name] = CopAnalysis.new(analysis.line_ranges, line)
165
+ end
166
+ end
167
+
115
168
  def inject_disabled_cops_directives(analyses)
116
169
  registry.disabled(config).each do |cop|
117
170
  analyses[cop.cop_name] = analyze_cop(
@@ -136,29 +189,21 @@ module RuboCop
136
189
  return analysis unless directive.disabled?
137
190
 
138
191
  line = directive.line_number
139
- start_line = analysis.start_line_number
140
-
141
- CopAnalysis.new(analysis.line_ranges + [(line..line)], start_line)
192
+ CopAnalysis.new(analysis.line_ranges + [(line..line)], analysis.start_line_number)
142
193
  end
143
194
 
144
195
  def analyze_disabled(analysis, directive)
145
196
  line = directive.line_number
146
197
  start_line = analysis.start_line_number
147
-
148
- # Cop already disabled on this line, so we end the current disabled
149
- # range before we start a new range.
150
- return CopAnalysis.new(analysis.line_ranges + [start_line..line], line) if start_line
151
-
152
- CopAnalysis.new(analysis.line_ranges, line)
198
+ new_ranges = start_line ? analysis.line_ranges + [start_line..line] : analysis.line_ranges
199
+ CopAnalysis.new(new_ranges, line)
153
200
  end
154
201
 
155
202
  def analyze_rest(analysis, directive)
156
203
  line = directive.line_number
157
204
  start_line = analysis.start_line_number
158
-
159
- return CopAnalysis.new(analysis.line_ranges + [start_line..line], nil) if start_line
160
-
161
- CopAnalysis.new(analysis.line_ranges, nil)
205
+ new_ranges = start_line ? analysis.line_ranges + [start_line..line] : analysis.line_ranges
206
+ CopAnalysis.new(new_ranges, nil)
162
207
  end
163
208
 
164
209
  def cop_line_ranges(analysis)
@@ -23,7 +23,7 @@ module RuboCop
23
23
  include FileFinder
24
24
 
25
25
  attr_accessor :debug, :ignore_parent_exclusion, :disable_pending_cops, :enable_pending_cops,
26
- :ignore_unrecognized_cops
26
+ :ignore_unrecognized_cops, :cache_root
27
27
  attr_writer :default_configuration
28
28
  attr_reader :loaded_plugins, :loaded_features
29
29
 
@@ -38,6 +38,7 @@ module RuboCop
38
38
  @enable_pending_cops = nil
39
39
  @ignore_parent_exclusion = nil
40
40
  @ignore_unrecognized_cops = nil
41
+ @cache_root = nil
41
42
  FileFinder.root_level = nil
42
43
  end
43
44
 
@@ -246,7 +246,7 @@ module RuboCop
246
246
  def inherited_file(path, inherit_from, file)
247
247
  if PathUtil.remote_file?(inherit_from)
248
248
  # A remote configuration, e.g. `inherit_from: http://example.com/rubocop.yml`.
249
- RemoteConfig.new(inherit_from, File.dirname(path))
249
+ RemoteConfig.new(inherit_from, ConfigLoader.cache_root)
250
250
  elsif Pathname.new(inherit_from).absolute?
251
251
  # An absolute path to a config, e.g. `inherit_from: /Users/me/rubocop.yml`.
252
252
  # The path may come from `inherit_gem` option, where a gem name is expanded
@@ -256,7 +256,7 @@ module RuboCop
256
256
  elsif file.is_a?(RemoteConfig)
257
257
  # A path relative to a URL, e.g. `inherit_from: configs/default.yml`
258
258
  # in a config included with `inherit_from: http://example.com/rubocop.yml`
259
- file.inherit_from_remote(inherit_from, path)
259
+ file.inherit_from_remote(inherit_from)
260
260
  else
261
261
  # A local relative path, e.g. `inherit_from: default.yml`
262
262
  print 'Inheriting ' if ConfigLoader.debug?
@@ -90,6 +90,8 @@ module RuboCop
90
90
  end
91
91
 
92
92
  def line_with_eol_comment_too_long?(range)
93
+ return false unless max_line_length
94
+
93
95
  (range.source_line + eol_comment).length > max_line_length
94
96
  end
95
97
 
@@ -133,6 +135,8 @@ module RuboCop
133
135
  end
134
136
 
135
137
  def max_line_length
138
+ return unless config.cop_enabled?('Layout/LineLength')
139
+
136
140
  config.for_cop('Layout/LineLength')['Max'] || 120
137
141
  end
138
142
 
@@ -43,8 +43,7 @@ module RuboCop
43
43
  def on_new_investigation
44
44
  return if processed_source.blank?
45
45
 
46
- gem_declarations(processed_source.ast)
47
- .each_cons(2) do |previous, current|
46
+ gem_declarations(processed_source.ast).each_cons(2) do |previous, current|
48
47
  next unless consecutive_lines?(previous, current)
49
48
  next unless case_insensitive_out_of_order?(gem_name(current), gem_name(previous))
50
49
 
@@ -76,9 +76,7 @@ module RuboCop
76
76
  # nil.
77
77
  # - The source map of `__FILE__` responds to neither :begin nor :end.
78
78
  def delimited_string_literal?(node)
79
- loc = node.location
80
-
81
- loc.respond_to?(:begin) && loc.begin && loc.respond_to?(:end) && loc.end
79
+ node.loc?(:begin) && node.loc?(:end)
82
80
  end
83
81
 
84
82
  def block_comment_within?(expr)
@@ -69,8 +69,7 @@ module RuboCop
69
69
  def on_new_investigation
70
70
  return if processed_source.blank?
71
71
 
72
- dependency_declarations(processed_source.ast)
73
- .each_cons(2) do |previous, current|
72
+ dependency_declarations(processed_source.ast).each_cons(2) do |previous, current|
74
73
  next unless consecutive_lines?(previous, current)
75
74
  next unless case_insensitive_out_of_order?(gem_name(current), gem_name(previous))
76
75
  next unless get_dependency_name(previous) == get_dependency_name(current)
@@ -3,8 +3,8 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Gemspec
6
- # Checks that `RUBY_VERSION` constant is not used in gemspec.
7
- # Using `RUBY_VERSION` is dangerous because value of the
6
+ # Checks that `RUBY_VERSION` and `Ruby::VERSION` constants are not used in gemspec.
7
+ # Using `RUBY_VERSION` and `Ruby::VERSION` are dangerous because value of the
8
8
  # constant is determined by `rake release`.
9
9
  # It's possible to have dependency based on ruby version used
10
10
  # to execute `rake release` and not user's ruby version.
@@ -28,15 +28,20 @@ module RuboCop
28
28
  class RubyVersionGlobalsUsage < Base
29
29
  include GemspecHelp
30
30
 
31
- MSG = 'Do not use `RUBY_VERSION` in gemspec file.'
31
+ MSG = 'Do not use `%<ruby_version>s` in gemspec file.'
32
32
 
33
33
  # @!method ruby_version?(node)
34
- def_node_matcher :ruby_version?, '(const {cbase nil?} :RUBY_VERSION)'
34
+ def_node_matcher :ruby_version?, <<~PATTERN
35
+ {
36
+ (const {cbase nil?} :RUBY_VERSION)
37
+ (const (const {cbase nil?} :Ruby) :VERSION)
38
+ }
39
+ PATTERN
35
40
 
36
41
  def on_const(node)
37
42
  return unless gem_spec_with_ruby_version?(node)
38
43
 
39
- add_offense(node)
44
+ add_offense(node, message: format(MSG, ruby_version: node.source))
40
45
  end
41
46
 
42
47
  private
@@ -9,6 +9,12 @@ module RuboCop
9
9
  #
10
10
  # @example
11
11
  # # bad
12
+ # node.loc.respond_to?(:begin)
13
+ #
14
+ # # good
15
+ # node.loc?(:begin)
16
+ #
17
+ # # bad
12
18
  # node.loc.respond_to?(:begin) && node.loc.begin
13
19
  #
14
20
  # # good
@@ -29,7 +35,16 @@ module RuboCop
29
35
  class LocationExists < Base
30
36
  extend AutoCorrector
31
37
 
32
- MSG = 'Use `%<replacement>s` instead of `%<source>s`.'
38
+ MSG = 'Use `node.loc?` instead of `loc.respond_to?`.'
39
+ MSG_CORRECTABLE = 'Use `%<replacement>s` instead of `%<source>s`.'
40
+ RESTRICT_ON_SEND = %i[respond_to?].freeze
41
+
42
+ # @!method loc_respond_to?(node)
43
+ def_node_matcher :loc_respond_to?, <<~PATTERN
44
+ (call
45
+ (call $_receiver :loc) :respond_to?
46
+ $(sym _location))
47
+ PATTERN
33
48
 
34
49
  # @!method replaceable_with_loc_is(node)
35
50
  def_node_matcher :replaceable_with_loc_is, <<~PATTERN
@@ -64,6 +79,15 @@ module RuboCop
64
79
  replace_with_loc(node) || replace_with_loc_is(node)
65
80
  end
66
81
 
82
+ def on_send(node)
83
+ return if ignored_node?(node.parent)
84
+
85
+ loc_respond_to?(node) do |receiver, location|
86
+ register_offense(node, replacement(receiver, "loc?(#{location.source})"))
87
+ end
88
+ end
89
+ alias on_csend on_send
90
+
67
91
  private
68
92
 
69
93
  def replace_with_loc(node)
@@ -84,11 +108,13 @@ module RuboCop
84
108
  end
85
109
 
86
110
  def register_offense(node, replacement)
87
- message = format(MSG, replacement: replacement, source: node.source)
111
+ message = format(MSG_CORRECTABLE, replacement: replacement, source: node.source)
88
112
 
89
113
  add_offense(node, message: message) do |corrector|
90
114
  corrector.replace(node, replacement)
91
115
  end
116
+
117
+ ignore_node(node)
92
118
  end
93
119
 
94
120
  def replacement(receiver, rest)
@@ -7,7 +7,7 @@ module RuboCop
7
7
  # AST Processor for NodePattern ASTs, for use with `InternalAffairs/NodePatternGroups`.
8
8
  #
9
9
  # Looks for sequences and subsequences where the first item is a `node_type` node,
10
- # and converts them to `node_sequence` nodes (not a true `Rubocop::AST::NodePattern`
10
+ # and converts them to `node_sequence` nodes (not a true `RuboCop::AST::NodePattern`
11
11
  # node type).
12
12
  #
13
13
  # The resulting AST will be walked by `InternalAffairs::NodePatternGroups::ASTWalker`
@@ -145,8 +145,10 @@ module RuboCop
145
145
  next_sibling.if_type? && contains_guard_clause?(next_sibling)
146
146
  end
147
147
 
148
+ # rubocop:disable Metrics/CyclomaticComplexity
148
149
  def last_heredoc_argument(node)
149
150
  n = last_heredoc_argument_node(node)
151
+ n = n.children.first while n.respond_to?(:begin_type?) && n.begin_type?
150
152
 
151
153
  return n if heredoc?(n)
152
154
  return unless n.respond_to?(:arguments)
@@ -158,6 +160,7 @@ module RuboCop
158
160
 
159
161
  last_heredoc_argument(n.receiver) if n.respond_to?(:receiver)
160
162
  end
163
+ # rubocop:enable Metrics/CyclomaticComplexity
161
164
 
162
165
  def last_heredoc_argument_node(node)
163
166
  return node unless node.respond_to?(:if_branch)
@@ -128,6 +128,10 @@ module RuboCop
128
128
  # assignment, we let rhs be the receiver of those method calls before
129
129
  # we check if it's an if/unless/while/until.
130
130
  return unless (rhs = first_part_of_call_chain(rhs))
131
+
132
+ # If `rhs` is a `begin` node, find the first non-`begin` child.
133
+ rhs = rhs.child_nodes.first while rhs.begin_type?
134
+
131
135
  return unless rhs.conditional?
132
136
  return if rhs.if_type? && rhs.ternary?
133
137
 
@@ -168,7 +168,7 @@ module RuboCop
168
168
 
169
169
  def subsequent_closing_parentheses_in_same_line?(outermost_send)
170
170
  last_arg_of_outer_send = outermost_send.last_argument
171
- return false unless last_arg_of_outer_send&.loc.respond_to?(:end) &&
171
+ return false unless last_arg_of_outer_send&.loc?(:end) &&
172
172
  (end_of_last_arg_of_outer_send = last_arg_of_outer_send.loc.end)
173
173
 
174
174
  end_of_outer_send = outermost_send.loc.end
@@ -230,7 +230,7 @@ module RuboCop
230
230
 
231
231
  def find_most_bottom_of_heredoc_end(arguments)
232
232
  arguments.filter_map do |argument|
233
- argument.loc.heredoc_end.end_pos if argument.loc.respond_to?(:heredoc_end)
233
+ argument.loc.heredoc_end.end_pos if argument.loc?(:heredoc_end)
234
234
  end.max
235
235
  end
236
236
 
@@ -89,6 +89,7 @@ module RuboCop
89
89
  end
90
90
 
91
91
  def line_too_long?(node)
92
+ return false unless max_line_length
92
93
  return false if unlimited_heredoc_length?
93
94
 
94
95
  body = heredoc_body(node)
@@ -108,10 +109,6 @@ module RuboCop
108
109
  config.for_cop('Layout/LineLength')['AllowHeredoc']
109
110
  end
110
111
 
111
- def max_line_length
112
- config.for_cop('Layout/LineLength')['Max']
113
- end
114
-
115
112
  def adjust_squiggly(corrector, node)
116
113
  corrector.replace(node.loc.heredoc_body, indented_body(node))
117
114
  corrector.replace(node.loc.heredoc_end, indented_end(node))
@@ -99,7 +99,7 @@ module RuboCop
99
99
 
100
100
  if str.heredoc?
101
101
  ranges << loc.heredoc_body
102
- elsif loc.respond_to?(:begin) && loc.begin
102
+ elsif str.loc?(:begin)
103
103
  ranges << loc.expression
104
104
  end
105
105
  end
@@ -83,7 +83,10 @@ module RuboCop
83
83
 
84
84
  return unless begins_its_line?(end_loc)
85
85
 
86
- check_indentation(end_loc, node.body)
86
+ # For blocks where the dot is on a new line, use the dot position as the base.
87
+ # Otherwise, use the end keyword position as the base.
88
+ base_loc = dot_on_new_line?(node) ? node.send_node.loc.dot : end_loc
89
+ check_indentation(base_loc, node.body)
87
90
 
88
91
  return unless indented_internal_methods_style?
89
92
 
@@ -383,6 +386,14 @@ module RuboCop
383
386
 
384
387
  leftmost_modifier_of(node.parent)
385
388
  end
389
+
390
+ def dot_on_new_line?(node)
391
+ send_node = node.send_node
392
+ return false unless send_node.loc?(:dot)
393
+
394
+ receiver = send_node.receiver
395
+ receiver && receiver.last_line < send_node.loc.dot.line
396
+ end
386
397
  end
387
398
  end
388
399
  end
@@ -101,7 +101,7 @@ module RuboCop
101
101
  ranges << loc.expression
102
102
  elsif literal.heredoc?
103
103
  ranges << loc.heredoc_body
104
- elsif (loc.respond_to?(:begin) && loc.begin) || ignored_parent?(literal)
104
+ elsif literal.loc?(:begin) || ignored_parent?(literal)
105
105
  ranges << loc.expression
106
106
  end
107
107
  end
@@ -252,17 +252,22 @@ module RuboCop
252
252
  [max - indentation_difference(line), 0].max
253
253
  end
254
254
 
255
+ # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
255
256
  def check_line(line, line_index)
256
257
  return if line_length(line) <= max
257
258
  return if allowed_line?(line, line_index)
259
+ if allow_rbs_inline_annotation? && rbs_inline_annotation_on_source_line?(line_index)
260
+ return
261
+ end
258
262
 
259
- if ignore_cop_directives? && directive_on_source_line?(line_index)
263
+ if allow_cop_directives? && directive_on_source_line?(line_index)
260
264
  return check_directive_line(line, line_index)
261
265
  end
262
266
  return check_line_for_exemptions(line, line_index) if allow_uri? || allow_qualified_name?
263
267
 
264
268
  register_offense(excess_range(nil, line, line_index), line, line_index)
265
269
  end
270
+ # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
266
271
 
267
272
  def allowed_line?(line, line_index)
268
273
  matches_allowed_pattern?(line) ||
@@ -306,6 +311,7 @@ module RuboCop
306
311
  def max
307
312
  cop_config['Max']
308
313
  end
314
+ alias max_line_length max
309
315
 
310
316
  def allow_heredoc?
311
317
  allowed_heredoc
@@ -401,9 +407,7 @@ module RuboCop
401
407
 
402
408
  def string_delimiter(node)
403
409
  delimiter = node.loc.begin
404
- if node.parent&.dstr_type? && node.parent.loc.respond_to?(:begin)
405
- delimiter ||= node.parent.loc.begin
406
- end
410
+ delimiter ||= node.parent.loc.begin if node.parent&.dstr_type? && node.parent.loc?(:begin)
407
411
  delimiter = delimiter&.source
408
412
 
409
413
  delimiter if %w[' "].include?(delimiter)
@@ -78,6 +78,8 @@ module RuboCop
78
78
  end
79
79
 
80
80
  def line_break_necessary_in_args?(node)
81
+ return false unless max_line_length
82
+
81
83
  needed_length_for_args(node) > max_line_length
82
84
  end
83
85
 
@@ -84,19 +84,23 @@ module RuboCop
84
84
  end
85
85
  end
86
86
 
87
+ # rubocop:disable Metrics/AbcSize
87
88
  def offending_range(node, lhs, rhs, given_style)
88
89
  return false unless begins_its_line?(rhs)
89
90
  return false if not_for_this_cop?(node)
90
91
 
91
92
  @base = alignment_base(node, rhs, given_style)
92
93
  correct_column = if @base
93
- @base.column + extra_indentation(given_style, node.parent)
94
+ parent = node.parent
95
+ parent = parent.parent if parent&.any_block_type?
96
+ @base.column + extra_indentation(given_style, parent)
94
97
  else
95
98
  indentation(lhs) + correct_indentation(node)
96
99
  end
97
100
  @column_delta = correct_column - rhs.column
98
101
  rhs if @column_delta.nonzero?
99
102
  end
103
+ # rubocop:enable Metrics/AbcSize
100
104
 
101
105
  def extra_indentation(given_style, parent)
102
106
  if given_style == :indented_relative_to_receiver