rubocop 1.75.8 → 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 (229) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +20 -16
  3. data/config/default.yml +142 -33
  4. data/config/obsoletion.yml +10 -3
  5. data/exe/rubocop +1 -8
  6. data/lib/rubocop/cli/command/auto_generate_config.rb +2 -2
  7. data/lib/rubocop/cli.rb +20 -4
  8. data/lib/rubocop/comment_config.rb +62 -17
  9. data/lib/rubocop/config_loader.rb +6 -40
  10. data/lib/rubocop/config_loader_resolver.rb +7 -6
  11. data/lib/rubocop/config_store.rb +5 -0
  12. data/lib/rubocop/cop/autocorrect_logic.rb +8 -4
  13. data/lib/rubocop/cop/bundler/ordered_gems.rb +2 -3
  14. data/lib/rubocop/cop/correctors/alignment_corrector.rb +8 -7
  15. data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +7 -2
  16. data/lib/rubocop/cop/correctors/parentheses_corrector.rb +5 -2
  17. data/lib/rubocop/cop/gemspec/attribute_assignment.rb +91 -0
  18. data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +0 -22
  19. data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +2 -3
  20. data/lib/rubocop/cop/gemspec/require_mfa.rb +15 -1
  21. data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +10 -5
  22. data/lib/rubocop/cop/internal_affairs/example_description.rb +1 -1
  23. data/lib/rubocop/cop/internal_affairs/location_exists.rb +28 -2
  24. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +4 -4
  25. data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_processor.rb +1 -1
  26. data/lib/rubocop/cop/internal_affairs/node_pattern_groups.rb +4 -1
  27. data/lib/rubocop/cop/internal_affairs/node_type_group.rb +3 -2
  28. data/lib/rubocop/cop/internal_affairs/on_send_without_on_csend.rb +1 -1
  29. data/lib/rubocop/cop/internal_affairs/useless_restrict_on_send.rb +1 -1
  30. data/lib/rubocop/cop/layout/class_structure.rb +1 -1
  31. data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +1 -1
  32. data/lib/rubocop/cop/layout/dot_position.rb +1 -1
  33. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +3 -0
  34. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +30 -12
  35. data/lib/rubocop/cop/layout/empty_lines_after_module_inclusion.rb +101 -0
  36. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +1 -1
  37. data/lib/rubocop/cop/layout/empty_lines_around_arguments.rb +8 -29
  38. data/lib/rubocop/cop/layout/empty_lines_around_class_body.rb +1 -1
  39. data/lib/rubocop/cop/layout/end_alignment.rb +4 -0
  40. data/lib/rubocop/cop/layout/hash_alignment.rb +2 -5
  41. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +2 -2
  42. data/lib/rubocop/cop/layout/heredoc_indentation.rb +1 -4
  43. data/lib/rubocop/cop/layout/indentation_style.rb +1 -1
  44. data/lib/rubocop/cop/layout/indentation_width.rb +12 -1
  45. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +1 -1
  46. data/lib/rubocop/cop/layout/line_length.rb +43 -10
  47. data/lib/rubocop/cop/layout/multiline_block_layout.rb +2 -0
  48. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +5 -1
  49. data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +8 -4
  50. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +13 -3
  51. data/lib/rubocop/cop/layout/space_after_comma.rb +2 -10
  52. data/lib/rubocop/cop/layout/space_after_semicolon.rb +1 -1
  53. data/lib/rubocop/cop/layout/space_around_keyword.rb +7 -2
  54. data/lib/rubocop/cop/layout/space_around_operators.rb +8 -0
  55. data/lib/rubocop/cop/layout/space_before_brackets.rb +2 -9
  56. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +7 -2
  57. data/lib/rubocop/cop/layout/trailing_whitespace.rb +1 -1
  58. data/lib/rubocop/cop/lint/ambiguous_range.rb +5 -0
  59. data/lib/rubocop/cop/lint/circular_argument_reference.rb +47 -3
  60. data/lib/rubocop/cop/lint/constant_overwritten_in_rescue.rb +3 -2
  61. data/lib/rubocop/cop/lint/cop_directive_syntax.rb +14 -8
  62. data/lib/rubocop/cop/lint/debugger.rb +0 -2
  63. data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +4 -1
  64. data/lib/rubocop/cop/lint/duplicate_match_pattern.rb +4 -4
  65. data/lib/rubocop/cop/lint/duplicate_methods.rb +25 -4
  66. data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +5 -42
  67. data/lib/rubocop/cop/lint/else_layout.rb +19 -0
  68. data/lib/rubocop/cop/lint/empty_interpolation.rb +14 -1
  69. data/lib/rubocop/cop/lint/float_comparison.rb +4 -4
  70. data/lib/rubocop/cop/lint/identity_comparison.rb +19 -15
  71. data/lib/rubocop/cop/lint/literal_as_condition.rb +38 -28
  72. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +1 -1
  73. data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +17 -8
  74. data/lib/rubocop/cop/lint/no_return_in_begin_end_blocks.rb +4 -0
  75. data/lib/rubocop/cop/lint/numeric_operation_with_constant_result.rb +1 -0
  76. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +23 -9
  77. data/lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb +1 -1
  78. data/lib/rubocop/cop/lint/redundant_require_statement.rb +4 -2
  79. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +101 -2
  80. data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +7 -1
  81. data/lib/rubocop/cop/lint/redundant_type_conversion.rb +4 -4
  82. data/lib/rubocop/cop/lint/require_range_parentheses.rb +1 -1
  83. data/lib/rubocop/cop/lint/rescue_exception.rb +1 -4
  84. data/lib/rubocop/cop/lint/rescue_type.rb +1 -1
  85. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +4 -4
  86. data/lib/rubocop/cop/lint/self_assignment.rb +39 -5
  87. data/lib/rubocop/cop/lint/shadowed_argument.rb +7 -7
  88. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +5 -0
  89. data/lib/rubocop/cop/lint/unreachable_code.rb +5 -3
  90. data/lib/rubocop/cop/lint/uri_escape_unescape.rb +2 -0
  91. data/lib/rubocop/cop/lint/useless_access_modifier.rb +29 -4
  92. data/lib/rubocop/cop/lint/useless_assignment.rb +44 -16
  93. data/lib/rubocop/cop/lint/useless_default_value_argument.rb +90 -0
  94. data/lib/rubocop/cop/lint/useless_numeric_operation.rb +1 -0
  95. data/lib/rubocop/cop/lint/useless_or.rb +111 -0
  96. data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +3 -3
  97. data/lib/rubocop/cop/lint/utils/nil_receiver_checker.rb +121 -0
  98. data/lib/rubocop/cop/lint/void.rb +7 -0
  99. data/lib/rubocop/cop/message_annotator.rb +1 -1
  100. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +4 -3
  101. data/lib/rubocop/cop/mixin/alignment.rb +1 -1
  102. data/lib/rubocop/cop/mixin/check_line_breakable.rb +1 -1
  103. data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +2 -4
  104. data/lib/rubocop/cop/mixin/code_length.rb +1 -1
  105. data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +1 -7
  106. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +1 -1
  107. data/lib/rubocop/cop/mixin/gemspec_help.rb +22 -0
  108. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +1 -1
  109. data/lib/rubocop/cop/mixin/line_length_help.rb +45 -10
  110. data/lib/rubocop/cop/mixin/method_complexity.rb +1 -1
  111. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +1 -1
  112. data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +1 -1
  113. data/lib/rubocop/cop/mixin/ordered_gem_node.rb +1 -1
  114. data/lib/rubocop/cop/mixin/space_after_punctuation.rb +5 -4
  115. data/lib/rubocop/cop/mixin/statement_modifier.rb +0 -6
  116. data/lib/rubocop/cop/mixin/trailing_comma.rb +8 -5
  117. data/lib/rubocop/cop/naming/file_name.rb +2 -2
  118. data/lib/rubocop/cop/naming/method_name.rb +129 -13
  119. data/lib/rubocop/cop/naming/predicate_method.rb +319 -0
  120. data/lib/rubocop/cop/naming/{predicate_name.rb → predicate_prefix.rb} +4 -4
  121. data/lib/rubocop/cop/security/eval.rb +2 -1
  122. data/lib/rubocop/cop/security/json_load.rb +33 -11
  123. data/lib/rubocop/cop/security/open.rb +1 -0
  124. data/lib/rubocop/cop/style/access_modifier_declarations.rb +1 -1
  125. data/lib/rubocop/cop/style/accessor_grouping.rb +13 -1
  126. data/lib/rubocop/cop/style/arguments_forwarding.rb +11 -17
  127. data/lib/rubocop/cop/style/array_intersect.rb +99 -35
  128. data/lib/rubocop/cop/style/array_intersect_with_single_element.rb +47 -0
  129. data/lib/rubocop/cop/style/bare_percent_literals.rb +1 -2
  130. data/lib/rubocop/cop/style/bitwise_predicate.rb +8 -1
  131. data/lib/rubocop/cop/style/block_delimiters.rb +1 -1
  132. data/lib/rubocop/cop/style/case_equality.rb +11 -13
  133. data/lib/rubocop/cop/style/case_like_if.rb +1 -1
  134. data/lib/rubocop/cop/style/class_and_module_children.rb +1 -0
  135. data/lib/rubocop/cop/style/collection_querying.rb +167 -0
  136. data/lib/rubocop/cop/style/conditional_assignment.rb +12 -16
  137. data/lib/rubocop/cop/style/constant_visibility.rb +17 -12
  138. data/lib/rubocop/cop/style/dig_chain.rb +1 -1
  139. data/lib/rubocop/cop/style/double_negation.rb +1 -1
  140. data/lib/rubocop/cop/style/empty_method.rb +0 -6
  141. data/lib/rubocop/cop/style/empty_string_inside_interpolation.rb +100 -0
  142. data/lib/rubocop/cop/style/endless_method.rb +15 -2
  143. data/lib/rubocop/cop/style/explicit_block_argument.rb +1 -1
  144. data/lib/rubocop/cop/style/exponential_notation.rb +3 -2
  145. data/lib/rubocop/cop/style/fetch_env_var.rb +32 -6
  146. data/lib/rubocop/cop/style/float_division.rb +15 -1
  147. data/lib/rubocop/cop/style/guard_clause.rb +0 -11
  148. data/lib/rubocop/cop/style/hash_conversion.rb +16 -8
  149. data/lib/rubocop/cop/style/hash_syntax.rb +1 -1
  150. data/lib/rubocop/cop/style/if_unless_modifier.rb +16 -9
  151. data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
  152. data/lib/rubocop/cop/style/inverse_methods.rb +1 -1
  153. data/lib/rubocop/cop/style/it_assignment.rb +69 -12
  154. data/lib/rubocop/cop/style/it_block_parameter.rb +36 -15
  155. data/lib/rubocop/cop/style/map_to_hash.rb +1 -3
  156. data/lib/rubocop/cop/style/map_to_set.rb +1 -3
  157. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +4 -6
  158. data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +12 -1
  159. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +33 -4
  160. data/lib/rubocop/cop/style/min_max_comparison.rb +13 -5
  161. data/lib/rubocop/cop/style/module_member_existence_check.rb +74 -0
  162. data/lib/rubocop/cop/style/multiline_method_signature.rb +2 -4
  163. data/lib/rubocop/cop/style/nil_comparison.rb +9 -7
  164. data/lib/rubocop/cop/style/one_line_conditional.rb +17 -9
  165. data/lib/rubocop/cop/style/operator_method_call.rb +11 -2
  166. data/lib/rubocop/cop/style/parallel_assignment.rb +34 -22
  167. data/lib/rubocop/cop/style/redundant_argument.rb +2 -0
  168. data/lib/rubocop/cop/style/redundant_array_flatten.rb +50 -0
  169. data/lib/rubocop/cop/style/redundant_begin.rb +34 -0
  170. data/lib/rubocop/cop/style/redundant_condition.rb +1 -1
  171. data/lib/rubocop/cop/style/redundant_exception.rb +1 -1
  172. data/lib/rubocop/cop/style/redundant_fetch_block.rb +1 -9
  173. data/lib/rubocop/cop/style/redundant_format.rb +26 -5
  174. data/lib/rubocop/cop/style/redundant_freeze.rb +1 -1
  175. data/lib/rubocop/cop/style/redundant_interpolation.rb +12 -3
  176. data/lib/rubocop/cop/style/redundant_line_continuation.rb +1 -1
  177. data/lib/rubocop/cop/style/redundant_parentheses.rb +55 -16
  178. data/lib/rubocop/cop/style/redundant_percent_q.rb +1 -2
  179. data/lib/rubocop/cop/style/redundant_regexp_argument.rb +9 -0
  180. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +8 -0
  181. data/lib/rubocop/cop/style/redundant_self.rb +8 -5
  182. data/lib/rubocop/cop/style/redundant_sort.rb +7 -7
  183. data/lib/rubocop/cop/style/safe_navigation.rb +44 -12
  184. data/lib/rubocop/cop/style/semicolon.rb +23 -7
  185. data/lib/rubocop/cop/style/single_line_methods.rb +7 -4
  186. data/lib/rubocop/cop/style/sole_nested_conditional.rb +40 -3
  187. data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +1 -1
  188. data/lib/rubocop/cop/style/string_concatenation.rb +17 -13
  189. data/lib/rubocop/cop/style/super_arguments.rb +2 -2
  190. data/lib/rubocop/cop/style/symbol_array.rb +1 -1
  191. data/lib/rubocop/cop/style/symbol_proc.rb +1 -1
  192. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +45 -0
  193. data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +1 -1
  194. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +11 -11
  195. data/lib/rubocop/cop/style/unless_else.rb +10 -9
  196. data/lib/rubocop/cop/util.rb +2 -3
  197. data/lib/rubocop/cop/utils/format_string.rb +10 -0
  198. data/lib/rubocop/cop/variable_force/variable.rb +1 -1
  199. data/lib/rubocop/cop/variable_force.rb +25 -8
  200. data/lib/rubocop/cops_documentation_generator.rb +5 -4
  201. data/lib/rubocop/directive_comment.rb +46 -3
  202. data/lib/rubocop/formatter/disabled_config_formatter.rb +19 -5
  203. data/lib/rubocop/formatter/fuubar_style_formatter.rb +1 -1
  204. data/lib/rubocop/formatter/markdown_formatter.rb +1 -0
  205. data/lib/rubocop/formatter/offense_count_formatter.rb +1 -1
  206. data/lib/rubocop/formatter/pacman_formatter.rb +1 -0
  207. data/lib/rubocop/lsp/diagnostic.rb +14 -18
  208. data/lib/rubocop/lsp/routes.rb +35 -6
  209. data/lib/rubocop/lsp/stdin_runner.rb +0 -16
  210. data/lib/rubocop/magic_comment.rb +20 -0
  211. data/lib/rubocop/pending_cops_reporter.rb +56 -0
  212. data/lib/rubocop/rake_task.rb +1 -1
  213. data/lib/rubocop/remote_config.rb +7 -8
  214. data/lib/rubocop/result_cache.rb +51 -38
  215. data/lib/rubocop/rspec/expect_offense.rb +9 -3
  216. data/lib/rubocop/rspec/shared_contexts.rb +2 -2
  217. data/lib/rubocop/rspec/support.rb +1 -1
  218. data/lib/rubocop/runner.rb +10 -4
  219. data/lib/rubocop/server/cache.rb +4 -2
  220. data/lib/rubocop/server/client_command/base.rb +10 -0
  221. data/lib/rubocop/server/client_command/exec.rb +2 -1
  222. data/lib/rubocop/server/client_command/start.rb +11 -1
  223. data/lib/rubocop/target_finder.rb +9 -9
  224. data/lib/rubocop/target_ruby.rb +11 -2
  225. data/lib/rubocop/version.rb +1 -1
  226. data/lib/rubocop.rb +13 -1
  227. data/lib/ruby_lsp/rubocop/addon.rb +25 -10
  228. data/lib/ruby_lsp/rubocop/runtime_adapter.rb +49 -15
  229. metadata +20 -8
@@ -14,11 +14,17 @@ module RuboCop
14
14
  # @api private
15
15
  COP_NAME_PATTERN = '([A-Za-z]\w+/)*(?:[A-Za-z]\w+)'
16
16
  # @api private
17
+ COP_NAME_PATTERN_NC = '(?:[A-Za-z]\w+/)*[A-Za-z]\w+'
18
+ # @api private
19
+ COP_NAMES_PATTERN_NC = "(?:#{COP_NAME_PATTERN_NC} , )*#{COP_NAME_PATTERN_NC}"
20
+ # @api private
17
21
  COP_NAMES_PATTERN = "(?:#{COP_NAME_PATTERN} , )*#{COP_NAME_PATTERN}"
18
22
  # @api private
19
23
  COPS_PATTERN = "(all|#{COP_NAMES_PATTERN})"
20
24
  # @api private
21
- AVAILABLE_MODES = %w[disable enable todo].freeze
25
+ PUSH_POP_ARGS_PATTERN = "([+\\-]#{COP_NAME_PATTERN_NC}(?:\\s+[+\\-]#{COP_NAME_PATTERN_NC})*)"
26
+ # @api private
27
+ AVAILABLE_MODES = %w[disable enable todo push pop].freeze
22
28
  # @api private
23
29
  DIRECTIVE_MARKER_PATTERN = '# rubocop : '
24
30
  # @api private
@@ -27,7 +33,7 @@ module RuboCop
27
33
  DIRECTIVE_HEADER_PATTERN = "#{DIRECTIVE_MARKER_PATTERN}((?:#{AVAILABLE_MODES.join('|')}))\\b"
28
34
  # @api private
29
35
  DIRECTIVE_COMMENT_REGEXP = Regexp.new(
30
- "#{DIRECTIVE_HEADER_PATTERN} #{COPS_PATTERN}"
36
+ "#{DIRECTIVE_HEADER_PATTERN}(?:\\s+#{COPS_PATTERN}|\\s+#{PUSH_POP_ARGS_PATTERN})?"
31
37
  .gsub(' ', '\s*')
32
38
  )
33
39
  # @api private
@@ -58,6 +64,7 @@ module RuboCop
58
64
  # Checks if the comment is malformed as a `# rubocop:` directive
59
65
  def malformed?
60
66
  return true if !start_with_marker? || @match_data.nil?
67
+ return true if missing_cop_name?
61
68
 
62
69
  tail = @match_data.post_match.lstrip
63
70
  !(tail.empty? || tail.start_with?(TRAILING_COMMENT_MARKER))
@@ -65,6 +72,8 @@ module RuboCop
65
72
 
66
73
  # Checks if the directive comment is missing a cop name
67
74
  def missing_cop_name?
75
+ return false if push? || pop?
76
+
68
77
  MALFORMED_DIRECTIVE_WITHOUT_COP_NAME_REGEXP.match?(comment.text)
69
78
  end
70
79
 
@@ -88,7 +97,13 @@ module RuboCop
88
97
 
89
98
  # Returns match captures to directive comment pattern
90
99
  def match_captures
91
- @match_captures ||= @match_data&.captures
100
+ @match_captures ||= @match_data && begin
101
+ captures = @match_data.captures
102
+ mode = captures[0]
103
+ # COPS_PATTERN is at captures[1], PUSH_POP_ARGS_PATTERN is at captures[4]
104
+ cops = captures[1] || captures[4]
105
+ [mode, cops]
106
+ end
92
107
  end
93
108
 
94
109
  # Checks if this directive disables cops
@@ -101,6 +116,21 @@ module RuboCop
101
116
  mode == 'enable'
102
117
  end
103
118
 
119
+ # Checks if this directive is a push
120
+ def push?
121
+ mode == 'push'
122
+ end
123
+
124
+ # Checks if this directive is a pop
125
+ def pop?
126
+ mode == 'pop'
127
+ end
128
+
129
+ # Returns the push arguments as a hash of cop names with their operations
130
+ def push_args
131
+ @push_args ||= parse_push_args
132
+ end
133
+
104
134
  # Checks if this directive enables all cops
105
135
  def enabled_all?
106
136
  !disabled? && all_cops?
@@ -176,5 +206,18 @@ module RuboCop
176
206
  def exclude_lint_department_cops(cops)
177
207
  cops - [LINT_REDUNDANT_DIRECTIVE_COP, LINT_SYNTAX_COP]
178
208
  end
209
+
210
+ def parse_push_args
211
+ return {} unless push? && cops
212
+
213
+ args = {}
214
+ cops.split.each do |cop_spec|
215
+ op = cop_spec[0]
216
+ cop_name = cop_spec[1..]
217
+ args[op] ||= []
218
+ args[op] << cop_name
219
+ end
220
+ args
221
+ end
179
222
  end
180
223
  end
@@ -4,7 +4,7 @@ module RuboCop
4
4
  module Formatter
5
5
  # This formatter displays a YAML configuration file where all cops that
6
6
  # detected any offenses are configured to not detect the offense.
7
- class DisabledConfigFormatter < BaseFormatter
7
+ class DisabledConfigFormatter < BaseFormatter # rubocop:disable Metrics/ClassLength
8
8
  include PathUtil
9
9
 
10
10
  HEADING = <<~COMMENTS
@@ -17,6 +17,23 @@ module RuboCop
17
17
  # versions of RuboCop, may require this file to be generated again.
18
18
  COMMENTS
19
19
 
20
+ EXCLUDED_CONFIG_KEYS = %w[
21
+ AutoCorrect
22
+ Description
23
+ Enabled
24
+ Exclude
25
+ Include
26
+ Reference
27
+ References
28
+ Safe
29
+ SafeAutoCorrect
30
+ Severity
31
+ StyleGuide
32
+ VersionAdded
33
+ VersionChanged
34
+ VersionRemoved
35
+ ].freeze
36
+
20
37
  @config_to_allow_offenses = {}
21
38
  @detected_styles = {}
22
39
 
@@ -163,10 +180,7 @@ module RuboCop
163
180
  end
164
181
 
165
182
  def cop_config_params(default_cfg, cfg)
166
- default_cfg.keys -
167
- %w[Description StyleGuide Reference References Enabled Exclude Safe
168
- SafeAutoCorrect VersionAdded VersionChanged VersionRemoved] -
169
- cfg.keys
183
+ default_cfg.keys - EXCLUDED_CONFIG_KEYS - cfg.keys
170
184
  end
171
185
 
172
186
  def output_cop_param_comments(output_buffer, params, default_cfg)
@@ -22,7 +22,7 @@ module RuboCop
22
22
 
23
23
  @severest_offense = nil
24
24
 
25
- file_phrase = target_files.count == 1 ? 'file' : 'files'
25
+ file_phrase = target_files.one? ? 'file' : 'files'
26
26
 
27
27
  # 185/407 files |====== 45 ======> | ETA: 00:00:04
28
28
  # %c / %C | %w > %i | %e
@@ -6,6 +6,7 @@ module RuboCop
6
6
  class MarkdownFormatter < BaseFormatter
7
7
  include TextUtil
8
8
  include PathUtil
9
+
9
10
  attr_reader :files, :summary
10
11
 
11
12
  def initialize(output, options = {})
@@ -24,7 +24,7 @@ module RuboCop
24
24
 
25
25
  return unless output.tty?
26
26
 
27
- file_phrase = target_files.count == 1 ? 'file' : 'files'
27
+ file_phrase = target_files.one? ? 'file' : 'files'
28
28
 
29
29
  # 185/407 files |====== 45 ======> | ETA: 00:00:04
30
30
  # %c / %C | %w > %i | %e
@@ -9,6 +9,7 @@ module RuboCop
9
9
  # https://github.com/go-labs/rspec_pacman_formatter
10
10
  class PacmanFormatter < ClangStyleFormatter
11
11
  include TextUtil
12
+
12
13
  attr_accessor :progress_line
13
14
 
14
15
  FALLBACK_TERMINAL_WIDTH = 80
@@ -45,11 +45,11 @@ module RuboCop
45
45
  range: LanguageServer::Protocol::Interface::Range.new(
46
46
  start: LanguageServer::Protocol::Interface::Position.new(
47
47
  line: @offense.line - 1,
48
- character: highlighted.begin_pos
48
+ character: to_position_character(highlighted.begin_pos)
49
49
  ),
50
50
  end: LanguageServer::Protocol::Interface::Position.new(
51
51
  line: @offense.line - 1,
52
- character: highlighted.end_pos
52
+ character: to_position_character(highlighted.end_pos)
53
53
  )
54
54
  ),
55
55
  data: {
@@ -79,7 +79,7 @@ module RuboCop
79
79
  LanguageServer::Protocol::Interface::CodeDescription.new(href: doc_url)
80
80
  end
81
81
 
82
- # rubocop:disable Layout/LineLength, Metrics/MethodLength
82
+ # rubocop:disable Metrics/MethodLength
83
83
  def autocorrect_action
84
84
  LanguageServer::Protocol::Interface::CodeAction.new(
85
85
  title: "Autocorrect #{@offense.cop_name}",
@@ -98,7 +98,7 @@ module RuboCop
98
98
  is_preferred: true
99
99
  )
100
100
  end
101
- # rubocop:enable Layout/LineLength, Metrics/MethodLength
101
+ # rubocop:enable Metrics/MethodLength
102
102
 
103
103
  # rubocop:disable Metrics/MethodLength
104
104
  def offense_replacements
@@ -107,11 +107,11 @@ module RuboCop
107
107
  range: LanguageServer::Protocol::Interface::Range.new(
108
108
  start: LanguageServer::Protocol::Interface::Position.new(
109
109
  line: range.line - 1,
110
- character: range.column
110
+ character: to_position_character(range.column)
111
111
  ),
112
112
  end: LanguageServer::Protocol::Interface::Position.new(
113
113
  line: range.last_line - 1,
114
- character: range.last_column
114
+ character: to_position_character(range.last_column)
115
115
  )
116
116
  ),
117
117
  new_text: replacement
@@ -120,7 +120,7 @@ module RuboCop
120
120
  end
121
121
  # rubocop:enable Metrics/MethodLength
122
122
 
123
- # rubocop:disable Layout/LineLength, Metrics/MethodLength
123
+ # rubocop:disable Metrics/MethodLength
124
124
  def disable_line_action
125
125
  LanguageServer::Protocol::Interface::CodeAction.new(
126
126
  title: "Disable #{@offense.cop_name} for this line",
@@ -138,7 +138,7 @@ module RuboCop
138
138
  )
139
139
  )
140
140
  end
141
- # rubocop:enable Layout/LineLength, Metrics/MethodLength
141
+ # rubocop:enable Metrics/MethodLength
142
142
 
143
143
  def line_disable_comment
144
144
  new_text = if @offense.source_line.include?(' # rubocop:disable ')
@@ -149,7 +149,7 @@ module RuboCop
149
149
 
150
150
  eol = LanguageServer::Protocol::Interface::Position.new(
151
151
  line: @offense.line - 1,
152
- character: length_of_line(@offense.source_line)
152
+ character: to_position_character(@offense.source_line.length)
153
153
  )
154
154
 
155
155
  # TODO: fails for multiline strings - may be preferable to use block
@@ -162,16 +162,12 @@ module RuboCop
162
162
  [inline_comment]
163
163
  end
164
164
 
165
- def length_of_line(line)
166
- if @document_encoding == Encoding::UTF_16LE
167
- line_length = 0
168
- line.codepoints.each do |codepoint|
169
- line_length += 1
170
- line_length += 1 if codepoint > RubyLsp::Document::Scanner::SURROGATE_PAIR_START
171
- end
172
- line_length
165
+ def to_position_character(utf8_index)
166
+ str = @offense.source_line[0, utf8_index]
167
+ if @document_encoding == Encoding::UTF_16LE || @document_encoding.nil?
168
+ str.length + str.b.count("\xf0-\xff".b)
173
169
  else
174
- line.length
170
+ str.length
175
171
  end
176
172
  end
177
173
 
@@ -51,7 +51,7 @@ module RuboCop
51
51
  capabilities: LanguageServer::Protocol::Interface::ServerCapabilities.new(
52
52
  document_formatting_provider: true,
53
53
  text_document_sync: LanguageServer::Protocol::Interface::TextDocumentSyncOptions.new(
54
- change: LanguageServer::Protocol::Constant::TextDocumentSyncKind::FULL,
54
+ change: LanguageServer::Protocol::Constant::TextDocumentSyncKind::INCREMENTAL,
55
55
  open_close: true
56
56
  )
57
57
  )
@@ -76,7 +76,12 @@ module RuboCop
76
76
 
77
77
  handle 'textDocument/didChange' do |request|
78
78
  params = request[:params]
79
- result = diagnostic(params[:textDocument][:uri], params[:contentChanges][0][:text])
79
+ file_uri = params[:textDocument][:uri]
80
+ text = @text_cache[file_uri]
81
+ params[:contentChanges].each do |content|
82
+ text = change_text(text, content[:text], content[:range])
83
+ end
84
+ result = diagnostic(file_uri, text)
80
85
  @server.write(result)
81
86
  end
82
87
 
@@ -194,7 +199,7 @@ module RuboCop
194
199
  return []
195
200
  end
196
201
 
197
- new_text = @server.format(remove_file_protocol_from(file_uri), text, command: command)
202
+ new_text = @server.format(convert_file_uri_to_path(file_uri), text, command: command)
198
203
 
199
204
  return [] if new_text == text
200
205
 
@@ -214,13 +219,37 @@ module RuboCop
214
219
  method: 'textDocument/publishDiagnostics',
215
220
  params: {
216
221
  uri: file_uri,
217
- diagnostics: @server.offenses(remove_file_protocol_from(file_uri), text)
222
+ diagnostics: @server.offenses(convert_file_uri_to_path(file_uri), text)
218
223
  }
219
224
  }
220
225
  end
221
226
 
222
- def remove_file_protocol_from(uri)
223
- uri.delete_prefix('file://')
227
+ def change_text(orig_text, text, range)
228
+ return text unless range
229
+
230
+ start_pos = text_pos(orig_text, range[:start])
231
+ end_pos = text_pos(orig_text, range[:end])
232
+ text_bin = orig_text.b
233
+ text_bin[start_pos...end_pos] = text.b
234
+ text_bin.force_encoding(orig_text.encoding)
235
+ end
236
+
237
+ def text_pos(text, range)
238
+ line = range[:line]
239
+ char = range[:character]
240
+ pos = 0
241
+ text.each_line.with_index do |l, i|
242
+ if i == line
243
+ pos += l.encode('utf-16be').b[0, char * 2].encode('utf-8', 'utf-16be').bytesize
244
+ return pos
245
+ end
246
+ pos += l.bytesize
247
+ end
248
+ pos
249
+ end
250
+
251
+ def convert_file_uri_to_path(uri)
252
+ URI.decode_www_form_component(uri.delete_prefix('file://'))
224
253
  end
225
254
  end
226
255
  end
@@ -40,7 +40,6 @@ module RuboCop
40
40
  super(@options, config_store)
41
41
  end
42
42
 
43
- # rubocop:disable Metrics/MethodLength
44
43
  def run(path, contents, options, prism_result: nil)
45
44
  @options = options.merge(DEFAULT_RUBOCOP_OPTIONS)
46
45
  @options[:stdin] = contents
@@ -54,22 +53,7 @@ module RuboCop
54
53
  super([path])
55
54
 
56
55
  raise Interrupt if aborting?
57
- rescue RuboCop::Runner::InfiniteCorrectionLoop => e
58
- if defined?(::RubyLsp::Requests::Formatting::Error)
59
- raise ::RubyLsp::Requests::Formatting::Error, e.message
60
- end
61
-
62
- raise e
63
- rescue RuboCop::ValidationError => e
64
- raise ConfigurationError, e.message
65
- rescue StandardError => e
66
- if defined?(::RubyLsp::Requests::Formatting::Error)
67
- raise ::RubyLsp::Requests::Support::InternalRuboCopError, e
68
- end
69
-
70
- raise e
71
56
  end
72
- # rubocop:enable Metrics/MethodLength
73
57
 
74
58
  def formatted_source
75
59
  @options[:stdin]
@@ -11,6 +11,7 @@ module RuboCop
11
11
  KEYWORDS = {
12
12
  encoding: '(?:en)?coding',
13
13
  frozen_string_literal: 'frozen[_-]string[_-]literal',
14
+ rbs_inline: 'rbs_inline',
14
15
  shareable_constant_value: 'shareable[_-]constant[_-]value',
15
16
  typed: 'typed'
16
17
  }.freeze
@@ -36,6 +37,7 @@ module RuboCop
36
37
  def any?
37
38
  frozen_string_literal_specified? ||
38
39
  encoding_specified? ||
40
+ rbs_inline_specified? ||
39
41
  shareable_constant_value_specified? ||
40
42
  typed_specified?
41
43
  end
@@ -60,6 +62,10 @@ module RuboCop
60
62
  [true, false].include?(frozen_string_literal)
61
63
  end
62
64
 
65
+ def valid_rbs_inline_value?
66
+ %w[enabled disabled].include?(extract_rbs_inline_value)
67
+ end
68
+
63
69
  def valid_shareable_constant_value?
64
70
  %w[none literal experimental_everything experimental_copy].include?(shareable_constant_value)
65
71
  end
@@ -105,6 +111,10 @@ module RuboCop
105
111
  specified?(encoding)
106
112
  end
107
113
 
114
+ def rbs_inline_specified?
115
+ valid_rbs_inline_value?
116
+ end
117
+
108
118
  # Was the Sorbet `typed` sigil specified?
109
119
  #
110
120
  # @return [Boolean]
@@ -203,6 +213,9 @@ module RuboCop
203
213
  match(KEYWORDS[:frozen_string_literal])
204
214
  end
205
215
 
216
+ # Emacs comments cannot specify RBS::inline behavior.
217
+ def extract_rbs_inline_value; end
218
+
206
219
  def extract_shareable_constant_value
207
220
  match(KEYWORDS[:shareable_constant_value])
208
221
  end
@@ -242,6 +255,9 @@ module RuboCop
242
255
  # Vim comments cannot specify frozen string literal behavior.
243
256
  def frozen_string_literal; end
244
257
 
258
+ # Vim comments cannot specify RBS::inline behavior.
259
+ def extract_rbs_inline_value; end
260
+
245
261
  # Vim comments cannot specify shareable constant values behavior.
246
262
  def shareable_constant_value; end
247
263
 
@@ -296,6 +312,10 @@ module RuboCop
296
312
  extract(/\A\s*#\s*#{KEYWORDS[:frozen_string_literal]}:\s*#{TOKEN}\s*\z/io)
297
313
  end
298
314
 
315
+ def extract_rbs_inline_value
316
+ extract(/\A\s*#\s*#{KEYWORDS[:rbs_inline]}:\s*#{TOKEN}\s*\z/io)
317
+ end
318
+
299
319
  def extract_shareable_constant_value
300
320
  extract(/\A\s*#\s*#{KEYWORDS[:shareable_constant_value]}:\s*#{TOKEN}\s*\z/io)
301
321
  end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ # Reports information about pending cops that are not explicitly configured.
5
+ #
6
+ # This class is responsible for displaying warnings when new cops have been added to RuboCop
7
+ # but have not yet been enabled or disabled in the user's configuration.
8
+ # It provides a centralized way to determine whether such warnings should be shown,
9
+ # based on global flags or configuration settings.
10
+ class PendingCopsReporter
11
+ class << self
12
+ PENDING_BANNER = <<~BANNER
13
+ The following cops were added to RuboCop, but are not configured. Please set Enabled to either `true` or `false` in your `.rubocop.yml` file.
14
+
15
+ Please also note that you can opt-in to new cops by default by adding this to your config:
16
+ AllCops:
17
+ NewCops: enable
18
+ BANNER
19
+
20
+ attr_accessor :disable_pending_cops, :enable_pending_cops
21
+
22
+ def warn_if_needed(config)
23
+ return if possible_new_cops?(config)
24
+
25
+ pending_cops = pending_cops_only_qualified(config.pending_cops)
26
+ warn_on_pending_cops(pending_cops) unless pending_cops.empty?
27
+ end
28
+
29
+ private
30
+
31
+ def pending_cops_only_qualified(pending_cops)
32
+ pending_cops.select { |cop| Cop::Registry.qualified_cop?(cop.name) }
33
+ end
34
+
35
+ def possible_new_cops?(config)
36
+ disable_pending_cops || enable_pending_cops ||
37
+ config.disabled_new_cops? || config.enabled_new_cops?
38
+ end
39
+
40
+ def warn_on_pending_cops(pending_cops)
41
+ warn Rainbow(PENDING_BANNER).yellow
42
+
43
+ pending_cops.each { |cop| warn_pending_cop cop }
44
+
45
+ warn Rainbow('For more information: https://docs.rubocop.org/rubocop/versioning.html').yellow
46
+ end
47
+
48
+ def warn_pending_cop(cop)
49
+ version = cop.metadata['VersionAdded'] || 'N/A'
50
+
51
+ warn Rainbow("#{cop.name}: # new in #{version}").yellow
52
+ warn Rainbow(' Enabled: true').yellow
53
+ end
54
+ end
55
+ end
56
+ end
@@ -75,7 +75,7 @@ module RuboCop
75
75
  def setup_subtasks(name, *args, &task_block) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
76
76
  namespace(name) do
77
77
  # rubocop:todo Naming/InclusiveLanguage
78
- task(:auto_correct, *args) do
78
+ task(:auto_correct, *args) do |_, task_args|
79
79
  require 'rainbow'
80
80
  warn Rainbow(
81
81
  'rubocop:auto_correct task is deprecated; ' \
@@ -11,13 +11,13 @@ module RuboCop
11
11
 
12
12
  CACHE_LIFETIME = 24 * 60 * 60
13
13
 
14
- def initialize(url, base_dir)
14
+ def initialize(url, cache_root)
15
15
  begin
16
16
  @uri = URI.parse(url)
17
17
  rescue URI::InvalidURIError
18
18
  raise ConfigNotFoundError, "Failed to resolve configuration: '#{url}' is not a valid URI"
19
19
  end
20
- @base_dir = base_dir
20
+ @cache_root = cache_root
21
21
  end
22
22
 
23
23
  def file
@@ -27,16 +27,17 @@ module RuboCop
27
27
  next if response.is_a?(Net::HTTPNotModified)
28
28
  next if response.is_a?(SocketError)
29
29
 
30
+ FileUtils.mkdir_p(File.dirname(cache_path))
30
31
  File.write(cache_path, response.body)
31
32
  end
32
33
 
33
34
  cache_path
34
35
  end
35
36
 
36
- def inherit_from_remote(file, path)
37
+ def inherit_from_remote(file)
37
38
  new_uri = @uri.dup
38
39
  new_uri.path.gsub!(%r{/[^/]*$}, "/#{file.delete_prefix('./')}")
39
- RemoteConfig.new(new_uri.to_s, File.dirname(path))
40
+ RemoteConfig.new(new_uri.to_s, @cache_root)
40
41
  end
41
42
 
42
43
  private
@@ -80,7 +81,7 @@ module RuboCop
80
81
  end
81
82
 
82
83
  def cache_path
83
- File.expand_path(".rubocop-#{cache_name_from_uri}", @base_dir)
84
+ @cache_path ||= File.expand_path(".rubocop-remote-#{cache_name_from_uri}", @cache_root)
84
85
  end
85
86
 
86
87
  def cache_path_exists?
@@ -97,9 +98,7 @@ module RuboCop
97
98
  end
98
99
 
99
100
  def cache_name_from_uri
100
- uri = cloned_url
101
- uri.query = nil
102
- uri.to_s.gsub!(/[^0-9A-Za-z]/, '-')
101
+ "#{Digest::MD5.hexdigest(@uri.to_s)}.yml"
103
102
  end
104
103
 
105
104
  def cloned_url