rubocop 1.38.0 → 1.40.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (83) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +51 -11
  4. data/exe/rubocop +1 -1
  5. data/lib/rubocop/comment_config.rb +5 -0
  6. data/lib/rubocop/config.rb +5 -4
  7. data/lib/rubocop/config_loader.rb +5 -5
  8. data/lib/rubocop/config_loader_resolver.rb +1 -1
  9. data/lib/rubocop/cop/base.rb +2 -9
  10. data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +22 -6
  11. data/lib/rubocop/cop/internal_affairs/lambda_or_proc.rb +46 -0
  12. data/lib/rubocop/cop/internal_affairs.rb +1 -0
  13. data/lib/rubocop/cop/layout/line_continuation_leading_space.rb +29 -8
  14. data/lib/rubocop/cop/layout/space_inside_array_percent_literal.rb +3 -0
  15. data/lib/rubocop/cop/layout/space_inside_percent_literal_delimiters.rb +34 -0
  16. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +1 -1
  17. data/lib/rubocop/cop/lint/assignment_in_condition.rb +11 -1
  18. data/lib/rubocop/cop/lint/deprecated_constants.rb +8 -1
  19. data/lib/rubocop/cop/lint/duplicate_methods.rb +17 -8
  20. data/lib/rubocop/cop/lint/empty_block.rb +1 -5
  21. data/lib/rubocop/cop/lint/empty_conditional_body.rb +1 -1
  22. data/lib/rubocop/cop/lint/interpolation_check.rb +4 -3
  23. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +5 -0
  24. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +13 -3
  25. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +15 -6
  26. data/lib/rubocop/cop/lint/send_with_mixin_argument.rb +5 -4
  27. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +4 -3
  28. data/lib/rubocop/cop/lint/suppressed_exception.rb +1 -1
  29. data/lib/rubocop/cop/lint/void.rb +6 -6
  30. data/lib/rubocop/cop/metrics/abc_size.rb +1 -1
  31. data/lib/rubocop/cop/metrics/block_length.rb +9 -4
  32. data/lib/rubocop/cop/metrics/class_length.rb +9 -4
  33. data/lib/rubocop/cop/metrics/method_length.rb +9 -4
  34. data/lib/rubocop/cop/metrics/module_length.rb +9 -4
  35. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +5 -2
  36. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +24 -5
  37. data/lib/rubocop/cop/mixin/range_help.rb +23 -0
  38. data/lib/rubocop/cop/mixin/statement_modifier.rb +15 -1
  39. data/lib/rubocop/cop/mixin/visibility_help.rb +40 -5
  40. data/lib/rubocop/cop/registry.rb +23 -11
  41. data/lib/rubocop/cop/style/access_modifier_declarations.rb +1 -25
  42. data/lib/rubocop/cop/style/array_intersect.rb +111 -0
  43. data/lib/rubocop/cop/style/class_equality_comparison.rb +7 -5
  44. data/lib/rubocop/cop/style/collection_compact.rb +1 -1
  45. data/lib/rubocop/cop/style/guard_clause.rb +32 -5
  46. data/lib/rubocop/cop/style/hash_as_last_array_item.rb +1 -0
  47. data/lib/rubocop/cop/style/hash_each_methods.rb +32 -10
  48. data/lib/rubocop/cop/style/hash_except.rb +4 -0
  49. data/lib/rubocop/cop/style/if_with_semicolon.rb +2 -1
  50. data/lib/rubocop/cop/style/nil_lambda.rb +1 -1
  51. data/lib/rubocop/cop/style/object_then.rb +3 -0
  52. data/lib/rubocop/cop/style/operator_method_call.rb +13 -0
  53. data/lib/rubocop/cop/style/quoted_symbols.rb +1 -1
  54. data/lib/rubocop/cop/style/redundant_argument.rb +3 -0
  55. data/lib/rubocop/cop/style/redundant_constant_base.rb +72 -0
  56. data/lib/rubocop/cop/style/redundant_each.rb +13 -8
  57. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +12 -3
  58. data/lib/rubocop/cop/style/redundant_return.rb +7 -0
  59. data/lib/rubocop/cop/style/redundant_sort.rb +1 -1
  60. data/lib/rubocop/cop/style/require_order.rb +88 -0
  61. data/lib/rubocop/cop/style/safe_navigation.rb +35 -6
  62. data/lib/rubocop/cop/style/select_by_regexp.rb +8 -4
  63. data/lib/rubocop/cop/style/string_literals.rb +1 -5
  64. data/lib/rubocop/cop/style/symbol_proc.rb +2 -4
  65. data/lib/rubocop/cop/team.rb +1 -1
  66. data/lib/rubocop/cop/util.rb +2 -2
  67. data/lib/rubocop/cop/variable_force/assignment.rb +1 -1
  68. data/lib/rubocop/cop/variable_force.rb +20 -29
  69. data/lib/rubocop/cops_documentation_generator.rb +3 -4
  70. data/lib/rubocop/formatter/disabled_config_formatter.rb +17 -6
  71. data/lib/rubocop/formatter/html_formatter.rb +1 -1
  72. data/lib/rubocop/formatter.rb +3 -1
  73. data/lib/rubocop/optimized_patterns.rb +38 -0
  74. data/lib/rubocop/options.rb +9 -1
  75. data/lib/rubocop/path_util.rb +14 -2
  76. data/lib/rubocop/result_cache.rb +1 -1
  77. data/lib/rubocop/rspec/cop_helper.rb +4 -1
  78. data/lib/rubocop/rspec/support.rb +2 -2
  79. data/lib/rubocop/server/core.rb +16 -1
  80. data/lib/rubocop/target_ruby.rb +1 -1
  81. data/lib/rubocop/version.rb +1 -1
  82. data/lib/rubocop.rb +14 -6
  83. metadata +8 -3
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Style
6
+ # Sort `require` and `require_relative` in alphabetical order.
7
+ #
8
+ # @safety
9
+ # This cop's autocorrection is unsafe because it will obviously change the execution order.
10
+ #
11
+ # @example
12
+ # # bad
13
+ # require 'b'
14
+ # require 'a'
15
+ #
16
+ # # good
17
+ # require 'a'
18
+ # require 'b'
19
+ #
20
+ # # bad
21
+ # require_relative 'b'
22
+ # require_relative 'a'
23
+ #
24
+ # # good
25
+ # require_relative 'a'
26
+ # require_relative 'b'
27
+ #
28
+ # # good (sorted within each section separated by a blank line)
29
+ # require 'a'
30
+ # require 'd'
31
+ #
32
+ # require 'b'
33
+ # require 'c'
34
+ #
35
+ # # good
36
+ # require 'b'
37
+ # require_relative 'c'
38
+ # require 'a'
39
+ class RequireOrder < Base
40
+ extend AutoCorrector
41
+
42
+ include RangeHelp
43
+
44
+ RESTRICT_ON_SEND = %i[require require_relative].freeze
45
+
46
+ def on_send(node)
47
+ previous_older_sibling = find_previous_older_sibling(node)
48
+ return unless previous_older_sibling
49
+
50
+ add_offense(
51
+ node,
52
+ message: "Sort `#{node.method_name}` in alphabetical order."
53
+ ) do |corrector|
54
+ swap(
55
+ range_with_comments_and_lines(previous_older_sibling),
56
+ range_with_comments_and_lines(node),
57
+ corrector: corrector
58
+ )
59
+ end
60
+ end
61
+
62
+ private
63
+
64
+ def find_previous_older_sibling(node)
65
+ node.left_siblings.reverse.find do |sibling|
66
+ break unless sibling.send_type?
67
+ break unless sibling.method?(node.method_name)
68
+ break unless in_same_section?(sibling, node)
69
+
70
+ node.first_argument.source < sibling.first_argument.source
71
+ end
72
+ end
73
+
74
+ def in_same_section?(node1, node2)
75
+ !node1.location.expression.with(
76
+ end_pos: node2.location.expression.end_pos
77
+ ).source.include?("\n\n")
78
+ end
79
+
80
+ def swap(range1, range2, corrector:)
81
+ inserted = range2.source
82
+ corrector.insert_before(range1, inserted)
83
+ corrector.remove(range2)
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
@@ -50,6 +50,11 @@ module RuboCop
50
50
  # foo && foo.bar { |e| e.something }
51
51
  # foo && foo.bar(param) { |e| e.something }
52
52
  #
53
+ # foo ? foo.bar : nil
54
+ # foo.nil? ? nil : foo.bar
55
+ # !foo.nil? ? foo.bar : nil
56
+ # !foo ? nil : foo.bar
57
+ #
53
58
  # # good
54
59
  # foo&.bar
55
60
  # foo&.bar&.baz
@@ -105,6 +110,17 @@ module RuboCop
105
110
  }
106
111
  PATTERN
107
112
 
113
+ # @!method ternary_safe_navigation_candidate(node)
114
+ def_node_matcher :ternary_safe_navigation_candidate, <<~PATTERN
115
+ {
116
+ (if (send $_ {:nil? :!}) nil $_)
117
+
118
+ (if (send (send $_ :nil?) :!) $_ nil)
119
+
120
+ (if $_ $_ nil)
121
+ }
122
+ PATTERN
123
+
108
124
  # @!method not_nil_check?(node)
109
125
  def_node_matcher :not_nil_check?, '(send (send $_ :nil?) :!)'
110
126
 
@@ -118,9 +134,11 @@ module RuboCop
118
134
  check_node(node)
119
135
  end
120
136
 
137
+ private
138
+
121
139
  def check_node(node)
122
140
  checked_variable, receiver, method_chain, method = extract_parts(node)
123
- return unless receiver == checked_variable
141
+ return if receiver != checked_variable || receiver.nil?
124
142
  return if use_var_only_in_unless_modifier?(node, checked_variable)
125
143
  return if chain_length(method_chain, method) > max_chain_length
126
144
  return if unsafe_method_used?(method_chain, method)
@@ -133,10 +151,8 @@ module RuboCop
133
151
  node.if_type? && node.unless? && !method_called?(variable)
134
152
  end
135
153
 
136
- private
137
-
138
154
  def autocorrect(corrector, node)
139
- body = node.node_parts[1]
155
+ body = extract_body(node)
140
156
  method_call = method_call(node)
141
157
 
142
158
  corrector.remove(begin_range(node, body))
@@ -147,6 +163,14 @@ module RuboCop
147
163
  add_safe_nav_to_all_methods_in_chain(corrector, method_call, body)
148
164
  end
149
165
 
166
+ def extract_body(node)
167
+ if node.if_type? && node.ternary?
168
+ node.branches.find { |branch| !branch.nil_type? }
169
+ else
170
+ node.node_parts[1]
171
+ end
172
+ end
173
+
150
174
  def handle_comments(corrector, node, method_call)
151
175
  comments = comments(node)
152
176
  return if comments.empty?
@@ -174,7 +198,7 @@ module RuboCop
174
198
  end
175
199
 
176
200
  def allowed_if_condition?(node)
177
- node.else? || node.elsif? || node.ternary?
201
+ node.else? || node.elsif?
178
202
  end
179
203
 
180
204
  def method_call(node)
@@ -192,7 +216,12 @@ module RuboCop
192
216
  end
193
217
 
194
218
  def extract_parts_from_if(node)
195
- variable, receiver = modifier_if_safe_navigation_candidate(node)
219
+ variable, receiver =
220
+ if node.ternary?
221
+ ternary_safe_navigation_candidate(node)
222
+ else
223
+ modifier_if_safe_navigation_candidate(node)
224
+ end
196
225
 
197
226
  checked_variable, matching_receiver, method = extract_common_parts(receiver, variable)
198
227
 
@@ -49,7 +49,8 @@ module RuboCop
49
49
  MSG = 'Prefer `%<replacement>s` to `%<original_method>s` with a regexp match.'
50
50
  RESTRICT_ON_SEND = %i[select find_all reject].freeze
51
51
  REPLACEMENTS = { select: 'grep', find_all: 'grep', reject: 'grep_v' }.freeze
52
- REGEXP_METHODS = %i[match? =~].to_set.freeze
52
+ OPPOSITE_REPLACEMENTS = { select: 'grep_v', find_all: 'grep_v', reject: 'grep' }.freeze
53
+ REGEXP_METHODS = %i[match? =~ !~].to_set.freeze
53
54
 
54
55
  # @!method regexp_match?(node)
55
56
  def_node_matcher :regexp_match?, <<~PATTERN
@@ -90,8 +91,10 @@ module RuboCop
90
91
  return unless (regexp_method_send_node = extract_send_node(block_node))
91
92
  return if match_predicate_without_receiver?(regexp_method_send_node)
92
93
 
94
+ opposite = regexp_method_send_node.send_type? && regexp_method_send_node.method?(:!~)
93
95
  regexp = find_regexp(regexp_method_send_node, block_node)
94
- register_offense(node, block_node, regexp)
96
+
97
+ register_offense(node, block_node, regexp, opposite)
95
98
  end
96
99
 
97
100
  private
@@ -102,8 +105,9 @@ module RuboCop
102
105
  node.hash_type? || creates_hash?(node) || env_const?(node)
103
106
  end
104
107
 
105
- def register_offense(node, block_node, regexp)
106
- replacement = REPLACEMENTS[node.method_name.to_sym]
108
+ def register_offense(node, block_node, regexp, opposite)
109
+ method_name = node.method_name.to_sym
110
+ replacement = opposite ? OPPOSITE_REPLACEMENTS[method_name] : REPLACEMENTS[method_name]
107
111
  message = format(MSG, replacement: replacement, original_method: node.method_name)
108
112
 
109
113
  add_offense(block_node, message: message) do |corrector|
@@ -95,11 +95,7 @@ module RuboCop
95
95
  end
96
96
 
97
97
  def offense?(node)
98
- # If it's a string within an interpolation, then it's not an offense
99
- # for this cop.
100
- return false if inside_interpolation?(node)
101
-
102
- wrong_quotes?(node)
98
+ wrong_quotes?(node) && !inside_interpolation?(node)
103
99
  end
104
100
 
105
101
  def consistent_multiline?
@@ -7,7 +7,7 @@ module RuboCop
7
7
  #
8
8
  # If you prefer a style that allows block for method with arguments,
9
9
  # please set `true` to `AllowMethodsWithArguments`.
10
- # respond_to , and `define_method?` methods are allowed by default.
10
+ # `define_method?` methods are allowed by default.
11
11
  # These are customizable with `AllowedMethods` option.
12
12
  #
13
13
  # @safety
@@ -72,12 +72,10 @@ module RuboCop
72
72
  # # some comment
73
73
  # end
74
74
  #
75
- # @example AllowedMethods: [respond_to, define_method] (default)
75
+ # @example AllowedMethods: [define_method] (default)
76
76
  # # good
77
- # respond_to { |foo| foo.bar }
78
77
  # define_method(:foo) { |foo| foo.bar }
79
78
  #
80
- #
81
79
  # @example AllowedPatterns: [] (default)
82
80
  # # bad
83
81
  # something.map { |s| s.upcase }
@@ -38,7 +38,7 @@ module RuboCop
38
38
  new(cops, config, options)
39
39
  end
40
40
 
41
- # @return [Array<Cop::Cop>]
41
+ # @return [Array<Cop::Base>]
42
42
  def self.mobilize_cops(cop_classes, config, options = {})
43
43
  cop_classes = Registry.new(cop_classes.to_a, options) unless cop_classes.is_a?(Registry)
44
44
 
@@ -122,7 +122,7 @@ module RuboCop
122
122
  string.inspect
123
123
  else
124
124
  # In a single-quoted strings, double quotes don't need to be escaped
125
- "'#{string.gsub('\"', '"').gsub('\\') { '\\\\' }}'"
125
+ "'#{string.gsub('\\') { '\\\\' }.gsub('\"', '"')}'"
126
126
  end
127
127
  end
128
128
 
@@ -159,7 +159,7 @@ module RuboCop
159
159
  private
160
160
 
161
161
  def compatible_external_encoding_for?(src)
162
- src = src.dup if RUBY_VERSION < '2.3' || RUBY_ENGINE == 'jruby'
162
+ src = src.dup if RUBY_ENGINE == 'jruby'
163
163
  src.force_encoding(Encoding.default_external).valid_encoding?
164
164
  end
165
165
  end
@@ -83,7 +83,7 @@ module RuboCop
83
83
  end
84
84
 
85
85
  def multiple_assignment_node
86
- grandparent_node = node.parent ? node.parent.parent : nil
86
+ grandparent_node = node.parent&.parent
87
87
  return nil unless grandparent_node
88
88
  return nil unless grandparent_node.type == MULTIPLE_ASSIGNMENT_TYPE
89
89
  return nil unless node.parent.type == MULTIPLE_LEFT_HAND_SIDE_TYPE
@@ -108,34 +108,26 @@ module RuboCop
108
108
  :skip_children
109
109
  end
110
110
 
111
- # rubocop:disable Metrics/MethodLength, Metrics/CyclomaticComplexity
111
+ # rubocop:disable Layout/ClassStructure
112
+ NODE_HANDLER_METHOD_NAMES = [
113
+ [VARIABLE_ASSIGNMENT_TYPE, :process_variable_assignment],
114
+ [REGEXP_NAMED_CAPTURE_TYPE, :process_regexp_named_captures],
115
+ [MULTIPLE_ASSIGNMENT_TYPE, :process_variable_multiple_assignment],
116
+ [VARIABLE_REFERENCE_TYPE, :process_variable_referencing],
117
+ [RESCUE_TYPE, :process_rescue],
118
+ [ZERO_ARITY_SUPER_TYPE, :process_zero_arity_super],
119
+ [SEND_TYPE, :process_send],
120
+ *ARGUMENT_DECLARATION_TYPES.product([:process_variable_declaration]),
121
+ *OPERATOR_ASSIGNMENT_TYPES.product([:process_variable_operator_assignment]),
122
+ *LOOP_TYPES.product([:process_loop]),
123
+ *SCOPE_TYPES.product([:process_scope])
124
+ ].to_h.freeze
125
+ private_constant :NODE_HANDLER_METHOD_NAMES
126
+ # rubocop:enable Layout/ClassStructure
127
+
112
128
  def node_handler_method_name(node)
113
- case node.type
114
- when VARIABLE_ASSIGNMENT_TYPE
115
- :process_variable_assignment
116
- when REGEXP_NAMED_CAPTURE_TYPE
117
- :process_regexp_named_captures
118
- when MULTIPLE_ASSIGNMENT_TYPE
119
- :process_variable_multiple_assignment
120
- when VARIABLE_REFERENCE_TYPE
121
- :process_variable_referencing
122
- when RESCUE_TYPE
123
- :process_rescue
124
- when ZERO_ARITY_SUPER_TYPE
125
- :process_zero_arity_super
126
- when SEND_TYPE
127
- :process_send
128
- when *ARGUMENT_DECLARATION_TYPES
129
- :process_variable_declaration
130
- when *OPERATOR_ASSIGNMENT_TYPES
131
- :process_variable_operator_assignment
132
- when *LOOP_TYPES
133
- :process_loop
134
- when *SCOPE_TYPES
135
- :process_scope
136
- end
129
+ NODE_HANDLER_METHOD_NAMES[node.type]
137
130
  end
138
- # rubocop:enable Metrics/MethodLength, Metrics/CyclomaticComplexity
139
131
 
140
132
  def process_variable_declaration(node)
141
133
  variable_name = node.children.first
@@ -358,13 +350,12 @@ module RuboCop
358
350
  end
359
351
  end
360
352
 
361
- # Use Node#equal? for accurate check.
362
353
  def scanned_node?(node)
363
- scanned_nodes.any? { |scanned_node| scanned_node.equal?(node) }
354
+ scanned_nodes.include?(node)
364
355
  end
365
356
 
366
357
  def scanned_nodes
367
- @scanned_nodes ||= []
358
+ @scanned_nodes ||= Set.new.compare_by_identity
368
359
  end
369
360
 
370
361
  # Hooks invoked by VariableTable.
@@ -183,11 +183,10 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
183
183
  # rubocop:enable Metrics/CyclomaticComplexity,Metrics/MethodLength
184
184
 
185
185
  def to_table(header, content)
186
- # Specify `[separator=¦]` to prevent the regexp `|` is not used as a table separator.
187
- # See: https://docs.asciidoctor.org/asciidoc/latest/tables/data-format/#escape-the-cell-separator
188
- table = ['[separator=¦]', '|===', "| #{header.join(' | ')}\n\n"].join("\n")
186
+ table = ['|===', "| #{header.join(' | ')}\n\n"].join("\n")
189
187
  marked_contents = content.map do |plain_content|
190
- plain_content.map { |c| #{c}" }.join("\n")
188
+ # Escape `|` with backslash to prevent the regexp `|` is not used as a table separator.
189
+ plain_content.map { |c| "| #{c.gsub(/\|/, '\|')}" }.join("\n")
191
190
  end
192
191
  table << marked_contents.join("\n\n")
193
192
  table << "\n|===\n"
@@ -65,6 +65,10 @@ module RuboCop
65
65
  @options.fetch(:offense_counts, true)
66
66
  end
67
67
 
68
+ def auto_gen_enforced_style?
69
+ @options.fetch(:auto_gen_enforced_style, true)
70
+ end
71
+
68
72
  def command
69
73
  command = 'rubocop --auto-gen-config'
70
74
 
@@ -79,6 +83,8 @@ module RuboCop
79
83
 
80
84
  command += ' --no-auto-gen-timestamp' unless show_timestamp?
81
85
 
86
+ command += ' --no-auto-gen-enforced-style' unless auto_gen_enforced_style?
87
+
82
88
  command
83
89
  end
84
90
 
@@ -172,17 +178,22 @@ module RuboCop
172
178
  end
173
179
 
174
180
  def output_cop_config(output_buffer, cfg, cop_name)
175
- # 'Enabled' option will be put into file only if exclude
176
- # limit is exceeded.
177
- cfg_without_enabled = cfg.reject { |key| key == 'Enabled' }
178
-
181
+ filtered_cfg = filtered_config(cfg)
179
182
  output_buffer.puts "#{cop_name}:"
180
- cfg_without_enabled.each do |key, value|
183
+ filtered_cfg.each do |key, value|
181
184
  value = value[0] if value.is_a?(Array)
182
185
  output_buffer.puts " #{key}: #{value}"
183
186
  end
184
187
 
185
- output_offending_files(output_buffer, cfg_without_enabled, cop_name)
188
+ output_offending_files(output_buffer, filtered_cfg, cop_name)
189
+ end
190
+
191
+ def filtered_config(cfg)
192
+ # 'Enabled' option will be put into file only if exclude
193
+ # limit is exceeded.
194
+ rejected_keys = ['Enabled']
195
+ rejected_keys << 'EnforcedStyle' unless auto_gen_enforced_style?
196
+ cfg.reject { |key| rejected_keys.include?(key) }
186
197
  end
187
198
 
188
199
  def output_offending_files(output_buffer, cfg, cop_name)
@@ -1,9 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'base64'
3
4
  require 'cgi'
4
5
  require 'erb'
5
6
  require 'ostruct'
6
- require 'base64'
7
7
 
8
8
  module RuboCop
9
9
  module Formatter
@@ -6,6 +6,7 @@ module RuboCop
6
6
 
7
7
  require_relative 'formatter/base_formatter'
8
8
  require_relative 'formatter/simple_text_formatter'
9
+
9
10
  # relies on simple text
10
11
  require_relative 'formatter/clang_style_formatter'
11
12
  require_relative 'formatter/disabled_config_formatter'
@@ -18,11 +19,12 @@ module RuboCop
18
19
  require_relative 'formatter/junit_formatter'
19
20
  require_relative 'formatter/markdown_formatter'
20
21
  require_relative 'formatter/offense_count_formatter'
22
+ require_relative 'formatter/pacman_formatter'
21
23
  require_relative 'formatter/progress_formatter'
22
24
  require_relative 'formatter/quiet_formatter'
23
25
  require_relative 'formatter/tap_formatter'
24
26
  require_relative 'formatter/worst_offenders_formatter'
25
- require_relative 'formatter/pacman_formatter'
27
+
26
28
  # relies on progress formatter
27
29
  require_relative 'formatter/auto_gen_config_formatter'
28
30
 
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ # @api private
5
+ module OptimizedPatterns
6
+ # A wrapper around patterns array to perform optimized search.
7
+ # @api private
8
+ class PatternsSet
9
+ def initialize(patterns)
10
+ @strings = Set.new
11
+ @patterns = []
12
+ partition_patterns(patterns)
13
+ end
14
+
15
+ def match?(path)
16
+ @strings.include?(path) || @patterns.any? { |pattern| PathUtil.match_path?(pattern, path) }
17
+ end
18
+
19
+ private
20
+
21
+ def partition_patterns(patterns)
22
+ patterns.each do |pattern|
23
+ if pattern.is_a?(String) && !pattern.match?(/[*{\[?]/)
24
+ @strings << pattern
25
+ else
26
+ @patterns << pattern
27
+ end
28
+ end
29
+ end
30
+ end
31
+
32
+ @cache = {}.compare_by_identity
33
+
34
+ def self.from(patterns)
35
+ @cache[patterns] ||= PatternsSet.new(patterns)
36
+ end
37
+ end
38
+ end
@@ -167,6 +167,7 @@ module RuboCop
167
167
  option(opts, '--[no-]offense-counts')
168
168
  option(opts, '--[no-]auto-gen-only-exclude')
169
169
  option(opts, '--[no-]auto-gen-timestamp')
170
+ option(opts, '--[no-]auto-gen-enforced-style')
170
171
  end
171
172
  end
172
173
 
@@ -464,7 +465,7 @@ module RuboCop
464
465
 
465
466
  # This module contains help texts for command line options.
466
467
  # @api private
467
- module OptionsHelp
468
+ module OptionsHelp # rubocop:disable Metrics/ModuleLength
468
469
  MAX_EXCL = RuboCop::Options::DEFAULT_MAXIMUM_EXCLUSION_ITEMS.to_s
469
470
  FORMATTER_OPTION_LIST = RuboCop::Formatter::FormatterSet::BUILTIN_FORMATTERS_FOR_KEYS.keys
470
471
 
@@ -486,6 +487,13 @@ module RuboCop
486
487
  auto_gen_timestamp:
487
488
  ['Include the date and time when the --auto-gen-config',
488
489
  'was run in the file it generates. Default is true.'],
490
+ auto_gen_enforced_style:
491
+ ['Add a setting to the TODO configuration file to enforce',
492
+ 'the style used, rather than a per-file exclusion',
493
+ 'if one style is used in all files for cop with',
494
+ 'EnforcedStyle as a configurable option',
495
+ 'when the --auto-gen-config was run',
496
+ 'in the file it generates. Default is true.'],
489
497
  auto_gen_only_exclude:
490
498
  ['Generate only Exclude parameters and not Max',
491
499
  'when running --auto-gen-config, except if the',
@@ -33,11 +33,18 @@ module RuboCop
33
33
  end
34
34
  end
35
35
 
36
+ # rubocop:disable Metrics/MethodLength, Metrics/CyclomaticComplexity
36
37
  def match_path?(pattern, path)
37
38
  case pattern
38
39
  when String
39
- File.fnmatch?(pattern, path, File::FNM_PATHNAME | File::FNM_EXTGLOB) ||
40
- hidden_file_in_not_hidden_dir?(pattern, path)
40
+ matches =
41
+ if pattern == path
42
+ true
43
+ elsif pattern.match?(/[*{\[?]/)
44
+ File.fnmatch?(pattern, path, File::FNM_PATHNAME | File::FNM_EXTGLOB)
45
+ end
46
+
47
+ matches || hidden_file_in_not_hidden_dir?(pattern, path)
41
48
  when Regexp
42
49
  begin
43
50
  pattern.match?(path)
@@ -48,6 +55,7 @@ module RuboCop
48
55
  end
49
56
  end
50
57
  end
58
+ # rubocop:enable Metrics/MethodLength, Metrics/CyclomaticComplexity
51
59
 
52
60
  # Returns true for an absolute Unix or Windows path.
53
61
  def absolute?(path)
@@ -67,8 +75,12 @@ module RuboCop
67
75
  maybe_hidden_file?(path) && File.basename(path).start_with?('.')
68
76
  end
69
77
 
78
+ HIDDEN_FILE_PATTERN = "#{File::SEPARATOR}."
79
+
70
80
  # Loose check to reduce memory allocations
71
81
  def maybe_hidden_file?(path)
82
+ return false unless path.include?(HIDDEN_FILE_PATTERN)
83
+
72
84
  separator_index = path.rindex(File::SEPARATOR)
73
85
  return false unless separator_index
74
86
 
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'digest/sha1'
4
- require 'find'
5
4
  require 'etc'
5
+ require 'find'
6
6
  require 'zlib'
7
7
  require_relative 'cache_config'
8
8
 
@@ -44,7 +44,10 @@ module CopHelper
44
44
 
45
45
  def registry
46
46
  @registry ||= begin
47
- cops = configuration.keys.map { |cop| RuboCop::Cop::Registry.global.find_by_cop_name(cop) }
47
+ keys = configuration.keys
48
+ cops =
49
+ keys.map { |directive| RuboCop::Cop::Registry.global.find_cops_by_directive(directive) }
50
+ .flatten
48
51
  cops << cop_class if defined?(cop_class) && !cops.include?(cop_class)
49
52
  cops.compact!
50
53
  RuboCop::Cop::Registry.new(cops)
@@ -3,10 +3,10 @@
3
3
  # Require this file to load code that supports testing using RSpec.
4
4
 
5
5
  require_relative 'cop_helper'
6
- require_relative 'host_environment_simulation_helper'
7
- require_relative 'shared_contexts'
8
6
  require_relative 'expect_offense'
7
+ require_relative 'host_environment_simulation_helper'
9
8
  require_relative 'parallel_formatter'
9
+ require_relative 'shared_contexts'
10
10
 
11
11
  RSpec.configure do |config|
12
12
  config.include CopHelper
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'socket'
4
3
  require 'securerandom'
4
+ require 'socket'
5
5
 
6
6
  #
7
7
  # This code is based on https://github.com/fohte/rubocop-daemon.
@@ -17,6 +17,8 @@ module RuboCop
17
17
  # The core of server process. It starts TCP server and perform socket communication.
18
18
  # @api private
19
19
  class Core
20
+ JSON_FORMATS = %w[json j].freeze
21
+
20
22
  def self.token
21
23
  @token ||= SecureRandom.hex(4)
22
24
  end
@@ -57,6 +59,10 @@ module RuboCop
57
59
  def start_server(host, port)
58
60
  @server = TCPServer.open(host, port)
59
61
 
62
+ # JSON format does not expected output message when IDE integration with server mode.
63
+ # See: https://github.com/rubocop/rubocop/issues/11164
64
+ return if use_json_format?
65
+
60
66
  output_stream = ARGV.include?('--stderr') ? $stderr : $stdout
61
67
  output_stream.puts "RuboCop server starting on #{@server.addr[3]}:#{@server.addr[1]}."
62
68
  end
@@ -76,6 +82,15 @@ module RuboCop
76
82
  ensure
77
83
  socket.close
78
84
  end
85
+
86
+ def use_json_format?
87
+ return true if ARGV.include?('--format=json') || ARGV.include?('--format=j')
88
+ return false unless (index = ARGV.index('--format'))
89
+
90
+ format = ARGV[index + 1]
91
+
92
+ JSON_FORMATS.include?(format)
93
+ end
79
94
  end
80
95
  end
81
96
  end
@@ -84,7 +84,7 @@ module RuboCop
84
84
  # @api private
85
85
  class ToolVersionsFile < RubyVersionFile
86
86
  TOOL_VERSIONS_FILENAME = '.tool-versions'
87
- TOOL_VERSIONS_PATTERN = /\Aruby (?:ruby-)?(?<version>\d+\.\d+)/.freeze
87
+ TOOL_VERSIONS_PATTERN = /^(?:ruby )(?<version>\d+\.\d+)/.freeze
88
88
 
89
89
  def name
90
90
  "`#{TOOL_VERSIONS_FILENAME}`"
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  # This module holds the RuboCop version information.
5
5
  module Version
6
- STRING = '1.38.0'
6
+ STRING = '1.40.0'
7
7
 
8
8
  MSG = '%<version>s (using Parser %<parser_version>s, ' \
9
9
  'rubocop-ast %<rubocop_ast_version>s, ' \