rubocop 1.32.0 → 1.33.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 (46) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/config/default.yml +45 -16
  4. data/config/obsoletion.yml +23 -1
  5. data/lib/rubocop/cache_config.rb +29 -0
  6. data/lib/rubocop/cli/command/auto_genenerate_config.rb +2 -2
  7. data/lib/rubocop/cli/command/init_dotfile.rb +1 -1
  8. data/lib/rubocop/config_finder.rb +68 -0
  9. data/lib/rubocop/config_loader.rb +5 -45
  10. data/lib/rubocop/config_obsoletion/changed_parameter.rb +5 -0
  11. data/lib/rubocop/config_obsoletion/parameter_rule.rb +4 -0
  12. data/lib/rubocop/config_obsoletion.rb +7 -2
  13. data/lib/rubocop/cop/layout/block_end_newline.rb +32 -5
  14. data/lib/rubocop/cop/layout/first_argument_indentation.rb +6 -1
  15. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +21 -8
  16. data/lib/rubocop/cop/lint/debugger.rb +11 -1
  17. data/lib/rubocop/cop/lint/empty_conditional_body.rb +60 -1
  18. data/lib/rubocop/cop/lint/number_conversion.rb +24 -8
  19. data/lib/rubocop/cop/metrics/abc_size.rb +3 -1
  20. data/lib/rubocop/cop/metrics/block_length.rb +6 -7
  21. data/lib/rubocop/cop/metrics/method_length.rb +8 -8
  22. data/lib/rubocop/cop/mixin/allowed_methods.rb +15 -1
  23. data/lib/rubocop/cop/mixin/allowed_pattern.rb +9 -1
  24. data/lib/rubocop/cop/mixin/comments_help.rb +5 -1
  25. data/lib/rubocop/cop/mixin/method_complexity.rb +4 -9
  26. data/lib/rubocop/cop/naming/predicate_name.rb +24 -3
  27. data/lib/rubocop/cop/style/block_delimiters.rb +26 -7
  28. data/lib/rubocop/cop/style/class_and_module_children.rb +4 -4
  29. data/lib/rubocop/cop/style/class_equality_comparison.rb +32 -7
  30. data/lib/rubocop/cop/style/empty_heredoc.rb +15 -1
  31. data/lib/rubocop/cop/style/format_string_token.rb +21 -8
  32. data/lib/rubocop/cop/style/hash_except.rb +0 -4
  33. data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +5 -1
  34. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +7 -7
  35. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +11 -6
  36. data/lib/rubocop/cop/style/numeric_predicate.rb +28 -8
  37. data/lib/rubocop/cop/style/redundant_condition.rb +19 -4
  38. data/lib/rubocop/cop/style/redundant_sort.rb +21 -6
  39. data/lib/rubocop/cop/style/symbol_proc.rb +29 -9
  40. data/lib/rubocop/result_cache.rb +22 -20
  41. data/lib/rubocop/server/cache.rb +33 -1
  42. data/lib/rubocop/server/cli.rb +19 -2
  43. data/lib/rubocop/version.rb +1 -1
  44. data/lib/rubocop.rb +0 -1
  45. metadata +5 -4
  46. data/lib/rubocop/cop/mixin/ignored_methods.rb +0 -52
@@ -159,10 +159,6 @@ module RuboCop
159
159
  key_argument = node.argument_list.first.source
160
160
  body = extract_body_if_nagated(node.body)
161
161
  lhs, _method_name, rhs = *body
162
-
163
- return lhs if body.method?('include?')
164
- return lhs if body.method?('exclude?')
165
- return rhs if body.method?('in?')
166
162
  return if [lhs, rhs].map(&:source).none?(key_argument)
167
163
 
168
164
  [lhs, rhs].find { |operand| operand.source != key_argument }
@@ -12,7 +12,7 @@ module RuboCop
12
12
  private
13
13
 
14
14
  def require_parentheses(node)
15
- return if ignored_method?(node.method_name)
15
+ return if allowed_method_name?(node.method_name)
16
16
  return if matches_allowed_pattern?(node.method_name)
17
17
  return if eligible_for_parentheses_omission?(node)
18
18
  return unless node.arguments? && !node.parenthesized?
@@ -24,6 +24,10 @@ module RuboCop
24
24
  end
25
25
  end
26
26
 
27
+ def allowed_method_name?(name)
28
+ allowed_method?(name) || matches_allowed_pattern?(name)
29
+ end
30
+
27
31
  def eligible_for_parentheses_omission?(node)
28
32
  node.operator_method? || node.setter_method? || ignored_macro?(node)
29
33
  end
@@ -6,8 +6,8 @@ module RuboCop
6
6
  # Enforces the presence (default) or absence of parentheses in
7
7
  # method calls containing parameters.
8
8
  #
9
- # In the default style (require_parentheses), macro methods are ignored.
10
- # Additional methods can be added to the `IgnoredMethods`
9
+ # In the default style (require_parentheses), macro methods are allowed.
10
+ # Additional methods can be added to the `AllowedMethods`
11
11
  # or `AllowedPatterns` list. These options are
12
12
  # valid only in the default style. Macros can be included by
13
13
  # either setting `IgnoreMacros` to false or adding specific macros to
@@ -15,13 +15,13 @@ module RuboCop
15
15
  #
16
16
  # Precedence of options is all follows:
17
17
  #
18
- # 1. `IgnoredMethods`
18
+ # 1. `AllowedMethods`
19
19
  # 2. `AllowedPatterns`
20
20
  # 3. `IncludedMacros`
21
21
  #
22
22
  # eg. If a method is listed in both
23
- # `IncludedMacros` and `IgnoredMethods`, then the latter takes
24
- # precedence (that is, the method is ignored).
23
+ # `IncludedMacros` and `AllowedMethods`, then the latter takes
24
+ # precedence (that is, the method is allowed).
25
25
  #
26
26
  # In the alternative style (omit_parentheses), there are three additional
27
27
  # options.
@@ -65,7 +65,7 @@ module RuboCop
65
65
  # # Setter methods don't need parens
66
66
  # foo.bar = baz
67
67
  #
68
- # # okay with `puts` listed in `IgnoredMethods`
68
+ # # okay with `puts` listed in `AllowedMethods`
69
69
  # puts 'test'
70
70
  #
71
71
  # # okay with `^assert` listed in `AllowedPatterns`
@@ -197,7 +197,7 @@ module RuboCop
197
197
  require_relative 'method_call_with_args_parentheses/require_parentheses'
198
198
 
199
199
  include ConfigurableEnforcedStyle
200
- include IgnoredMethods
200
+ include AllowedMethods
201
201
  include AllowedPattern
202
202
  include RequireParentheses
203
203
  include OmitParentheses
@@ -5,8 +5,8 @@ module RuboCop
5
5
  module Style
6
6
  # Checks for unwanted parentheses in parameterless method calls.
7
7
  #
8
- # This cop can be customized ignored methods with `IgnoredMethods`.
9
- # By default, there are no methods to ignored.
8
+ # This cop can be customized allowed methods with `AllowedMethods`.
9
+ # By default, there are no methods to allowed.
10
10
  #
11
11
  # @example
12
12
  # # bad
@@ -15,16 +15,17 @@ module RuboCop
15
15
  # # good
16
16
  # object.some_method
17
17
  #
18
- # @example IgnoredMethods: [] (default)
18
+ # @example AllowedMethods: [] (default)
19
19
  # # bad
20
20
  # object.foo()
21
21
  #
22
- # @example IgnoredMethods: [foo]
22
+ # @example AllowedMethods: [foo]
23
23
  # # good
24
24
  # object.foo()
25
25
  #
26
26
  class MethodCallWithoutArgsParentheses < Base
27
- include IgnoredMethods
27
+ include AllowedMethods
28
+ include AllowedPattern
28
29
  extend AutoCorrector
29
30
 
30
31
  MSG = 'Do not use parentheses for method calls with no arguments.'
@@ -33,7 +34,7 @@ module RuboCop
33
34
  return unless !node.arguments? && node.parenthesized?
34
35
  return if ineligible_node?(node)
35
36
  return if default_argument?(node)
36
- return if ignored_method?(node.method_name)
37
+ return if allowed_method_name?(node.method_name)
37
38
  return if same_name_assignment?(node)
38
39
 
39
40
  register_offense(node)
@@ -56,6 +57,10 @@ module RuboCop
56
57
  node.parent&.optarg_type?
57
58
  end
58
59
 
60
+ def allowed_method_name?(name)
61
+ allowed_method?(name) || matches_allowed_pattern?(name)
62
+ end
63
+
59
64
  def same_name_assignment?(node)
60
65
  any_assignment?(node) do |asgn_node|
61
66
  next variable_in_mass_assignment?(node.method_name, asgn_node) if asgn_node.masgn_type?
@@ -8,14 +8,14 @@ module RuboCop
8
8
  # These can be replaced by their respective predicate methods.
9
9
  # This cop can also be configured to do the reverse.
10
10
  #
11
- # This cop can be customized ignored methods with `IgnoredMethods`.
12
- # By default, there are no methods to ignored.
11
+ # This cop can be customized allowed methods with `AllowedMethods`.
12
+ # By default, there are no methods to allowed.
13
13
  #
14
14
  # This cop disregards `#nonzero?` as its value is truthy or falsey,
15
15
  # but not `true` and `false`, and thus not always interchangeable with
16
16
  # `!= 0`.
17
17
  #
18
- # This cop ignores comparisons to global variables, since they are often
18
+ # This cop allows comparisons to global variables, since they are often
19
19
  # populated with objects which can be compared with integers, but are
20
20
  # not themselves `Integer` polymorphic.
21
21
  #
@@ -46,13 +46,13 @@ module RuboCop
46
46
  # 0 > foo
47
47
  # bar.baz > 0
48
48
  #
49
- # @example IgnoredMethods: [] (default) with EnforcedStyle: predicate
49
+ # @example AllowedMethods: [] (default) with EnforcedStyle: predicate
50
50
  # # bad
51
51
  # foo == 0
52
52
  # 0 > foo
53
53
  # bar.baz > 0
54
54
  #
55
- # @example IgnoredMethods: [==] with EnforcedStyle: predicate
55
+ # @example AllowedMethods: [==] with EnforcedStyle: predicate
56
56
  # # good
57
57
  # foo == 0
58
58
  #
@@ -60,9 +60,25 @@ module RuboCop
60
60
  # 0 > foo
61
61
  # bar.baz > 0
62
62
  #
63
+ # @example AllowedPatterns: [] (default) with EnforcedStyle: comparison
64
+ # # bad
65
+ # foo.zero?
66
+ # foo.negative?
67
+ # bar.baz.positive?
68
+ #
69
+ # @example AllowedPatterns: [/zero/] with EnforcedStyle: predicate
70
+ # # good
71
+ # # bad
72
+ # foo.zero?
73
+ #
74
+ # # bad
75
+ # foo.negative?
76
+ # bar.baz.positive?
77
+ #
63
78
  class NumericPredicate < Base
64
79
  include ConfigurableEnforcedStyle
65
- include IgnoredMethods
80
+ include AllowedMethods
81
+ include AllowedPattern
66
82
  extend AutoCorrector
67
83
 
68
84
  MSG = 'Use `%<prefer>s` instead of `%<current>s`.'
@@ -75,9 +91,9 @@ module RuboCop
75
91
  numeric, replacement = check(node)
76
92
  return unless numeric
77
93
 
78
- return if ignored_method?(node.method_name) ||
94
+ return if allowed_method_name?(node.method_name) ||
79
95
  node.each_ancestor(:send, :block).any? do |ancestor|
80
- ignored_method?(ancestor.method_name)
96
+ allowed_method_name?(ancestor.method_name)
81
97
  end
82
98
 
83
99
  message = format(MSG, prefer: replacement, current: node.source)
@@ -88,6 +104,10 @@ module RuboCop
88
104
 
89
105
  private
90
106
 
107
+ def allowed_method_name?(name)
108
+ allowed_method?(name) || matches_allowed_pattern?(name)
109
+ end
110
+
91
111
  def check(node)
92
112
  numeric, operator =
93
113
  if style == :predicate
@@ -154,16 +154,22 @@ module RuboCop
154
154
  if_branch.method?(else_branch.method_name) && if_branch.receiver == else_branch.receiver
155
155
  end
156
156
 
157
- def if_source(if_branch)
157
+ def if_source(if_branch, arithmetic_operation)
158
158
  if branches_have_method?(if_branch.parent) && if_branch.parenthesized?
159
159
  if_branch.source.delete_suffix(')')
160
+ elsif arithmetic_operation
161
+ argument_source = if_branch.first_argument.source
162
+
163
+ "#{if_branch.receiver.source} #{if_branch.method_name} (#{argument_source}"
160
164
  else
161
165
  if_branch.source
162
166
  end
163
167
  end
164
168
 
165
- def else_source(else_branch)
166
- if branches_have_method?(else_branch.parent)
169
+ def else_source(else_branch, arithmetic_operation) # rubocop:disable Metrics/AbcSize
170
+ if arithmetic_operation
171
+ "#{else_branch.first_argument.source})"
172
+ elsif branches_have_method?(else_branch.parent)
167
173
  else_source_if_has_method(else_branch)
168
174
  elsif require_parentheses?(else_branch)
169
175
  "(#{else_branch.source})"
@@ -198,7 +204,12 @@ module RuboCop
198
204
 
199
205
  def make_ternary_form(node)
200
206
  _condition, if_branch, else_branch = *node
201
- ternary_form = [if_source(if_branch), else_source(else_branch)].join(' || ')
207
+ arithmetic_operation = use_arithmetic_operation?(if_branch)
208
+
209
+ ternary_form = [
210
+ if_source(if_branch, arithmetic_operation),
211
+ else_source(else_branch, arithmetic_operation)
212
+ ].join(' || ')
202
213
  ternary_form += ')' if branches_have_method?(node) && if_branch.parenthesized?
203
214
 
204
215
  if node.parent&.send_type?
@@ -227,6 +238,10 @@ module RuboCop
227
238
  node.hash_type? && !node.braces?
228
239
  end
229
240
 
241
+ def use_arithmetic_operation?(node)
242
+ node.respond_to?(:arithmetic_operation?) && node.arithmetic_operation?
243
+ end
244
+
230
245
  def without_argument_parentheses_method?(node)
231
246
  node.send_type? && !node.arguments.empty? &&
232
247
  !node.parenthesized? && !node.operator_method? && !node.assignment_method?
@@ -123,13 +123,8 @@ module RuboCop
123
123
 
124
124
  def register_offense(node, sort_node, sorter, accessor)
125
125
  message = message(node, sorter, accessor)
126
-
127
126
  add_offense(offense_range(sort_node, node), message: message) do |corrector|
128
- # Remove accessor, e.g. `first` or `[-1]`.
129
- corrector.remove(range_between(accessor_start(node), node.loc.expression.end_pos))
130
-
131
- # Replace "sort" or "sort_by" with the appropriate min/max method.
132
- corrector.replace(sort_node.loc.selector, suggestion(sorter, accessor, arg_value(node)))
127
+ autocorrect(corrector, node, sort_node, sorter, accessor)
133
128
  end
134
129
  end
135
130
 
@@ -149,6 +144,20 @@ module RuboCop
149
144
  accessor_source: accessor_source)
150
145
  end
151
146
 
147
+ def autocorrect(corrector, node, sort_node, sorter, accessor)
148
+ # Remove accessor, e.g. `first` or `[-1]`.
149
+ corrector.remove(range_between(accessor_start(node), node.loc.expression.end_pos))
150
+ # Replace "sort" or "sort_by" with the appropriate min/max method.
151
+ corrector.replace(sort_node.loc.selector, suggestion(sorter, accessor, arg_value(node)))
152
+ # Replace to avoid syntax errors when followed by a logical operator.
153
+ replace_with_logical_operator(corrector, node) if with_logical_operator?(node)
154
+ end
155
+
156
+ def replace_with_logical_operator(corrector, node)
157
+ corrector.insert_after(node.child_nodes.first, " #{node.parent.loc.operator.source}")
158
+ corrector.remove(node.parent.loc.operator)
159
+ end
160
+
152
161
  def suggestion(sorter, accessor, arg)
153
162
  base(accessor, arg) + suffix(sorter)
154
163
  end
@@ -187,6 +196,12 @@ module RuboCop
187
196
  node.loc.selector.begin_pos
188
197
  end
189
198
  end
199
+
200
+ def with_logical_operator?(node)
201
+ return unless (parent = node.parent)
202
+
203
+ parent.or_type? || parent.and_type?
204
+ end
190
205
  end
191
206
  end
192
207
  end
@@ -7,13 +7,13 @@ 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 ignored by default.
11
- # These are customizable with `IgnoredMethods` option.
10
+ # respond_to , and `define_method?` methods are allowed by default.
11
+ # These are customizable with `AllowedMethods` option.
12
12
  #
13
13
  # @safety
14
14
  # This cop is unsafe because `proc`s and blocks work differently
15
15
  # when additional arguments are passed in. A block will silently
16
- # ignore additional arguments, but a `proc` will raise
16
+ # allow additional arguments, but a `proc` will raise
17
17
  # an `ArgumentError`.
18
18
  #
19
19
  # For example:
@@ -71,15 +71,25 @@ module RuboCop
71
71
  # # some comment
72
72
  # end
73
73
  #
74
- # @example IgnoredMethods: [respond_to, define_method] (default)
74
+ # @example AllowedMethods: [respond_to, define_method] (default)
75
75
  # # good
76
76
  # respond_to { |foo| foo.bar }
77
77
  # define_method(:foo) { |foo| foo.bar }
78
78
  #
79
+ #
80
+ # @example AllowedPatterns: [] (default)
81
+ # # bad
82
+ # something.map { |s| s.upcase }
83
+ #
84
+ # @example AllowedPatterns: [/map/] (default)
85
+ # # good
86
+ # something.map { |s| s.upcase }
87
+ #
79
88
  class SymbolProc < Base
80
89
  include CommentsHelp
81
90
  include RangeHelp
82
- include IgnoredMethods
91
+ include AllowedMethods
92
+ include AllowedPattern
83
93
  extend AutoCorrector
84
94
 
85
95
  MSG = 'Pass `&:%<method>s` as an argument to `%<block_method>s` instead of a block.'
@@ -103,15 +113,16 @@ module RuboCop
103
113
  [Layout::SpaceBeforeBlockBraces]
104
114
  end
105
115
 
106
- # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
116
+ # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
107
117
  def on_block(node)
108
118
  symbol_proc?(node) do |dispatch_node, arguments_node, method_name|
109
119
  # TODO: Rails-specific handling that we should probably make
110
120
  # configurable - https://github.com/rubocop/rubocop/issues/1485
111
- # we should ignore lambdas & procs
121
+ # we should allow lambdas & procs
112
122
  return if proc_node?(dispatch_node)
123
+ return if unsafe_hash_usage?(dispatch_node)
113
124
  return if %i[lambda proc].include?(dispatch_node.method_name)
114
- return if ignored_method?(dispatch_node.method_name)
125
+ return if allowed_method_name?(dispatch_node.method_name)
115
126
  return if allow_if_method_has_argument?(node.send_node)
116
127
  return if node.block_type? && destructuring_block_argument?(arguments_node)
117
128
  return if allow_comments? && contains_comments?(node)
@@ -119,7 +130,7 @@ module RuboCop
119
130
  register_offense(node, method_name, dispatch_node.method_name)
120
131
  end
121
132
  end
122
- # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
133
+ # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
123
134
  alias on_numblock on_block
124
135
 
125
136
  def destructuring_block_argument?(argument_node)
@@ -128,6 +139,15 @@ module RuboCop
128
139
 
129
140
  private
130
141
 
142
+ # See: https://github.com/rubocop/rubocop/issues/10864
143
+ def unsafe_hash_usage?(node)
144
+ node.receiver&.hash_type? && %i[reject select].include?(node.method_name)
145
+ end
146
+
147
+ def allowed_method_name?(name)
148
+ allowed_method?(name) || matches_allowed_pattern?(name)
149
+ end
150
+
131
151
  def register_offense(node, method_name, block_method_name)
132
152
  block_start = node.loc.begin.begin_pos
133
153
  block_end = node.loc.end.end_pos
@@ -4,6 +4,7 @@ require 'digest/sha1'
4
4
  require 'find'
5
5
  require 'etc'
6
6
  require 'zlib'
7
+ require_relative 'cache_config'
7
8
 
8
9
  module RuboCop
9
10
  # Provides functionality for caching RuboCop runs.
@@ -13,6 +14,12 @@ module RuboCop
13
14
  fix_layout autocorrect safe_autocorrect autocorrect_all
14
15
  cache fail_fast stdin parallel].freeze
15
16
 
17
+ DL_EXTENSIONS = ::RbConfig::CONFIG
18
+ .values_at('DLEXT', 'DLEXT2')
19
+ .reject { |ext| !ext || ext.empty? }
20
+ .map { |ext| ".#{ext}" }
21
+ .freeze
22
+
16
23
  # Remove old files so that the cache doesn't grow too big. When the
17
24
  # threshold MaxFilesInCache has been exceeded, the oldest 50% of all the
18
25
  # files in the cache are removed. The reason for removing so much is that
@@ -67,24 +74,9 @@ module RuboCop
67
74
  end
68
75
 
69
76
  def self.cache_root(config_store)
70
- root = ENV.fetch('RUBOCOP_CACHE_ROOT', nil)
71
- root ||= config_store.for_pwd.for_all_cops['CacheRootDirectory']
72
- root ||= if ENV.key?('XDG_CACHE_HOME')
73
- # Include user ID in the path to make sure the user has write
74
- # access.
75
- File.join(ENV.fetch('XDG_CACHE_HOME'), Process.uid.to_s)
76
- else
77
- # On FreeBSD, the /home path is a symbolic link to /usr/home
78
- # and the $HOME environment variable returns the /home path.
79
- #
80
- # As $HOME is a built-in environment variable, FreeBSD users
81
- # always get a warning message.
82
- #
83
- # To avoid raising warn log messages on FreeBSD, we retrieve
84
- # the real path of the home folder.
85
- File.join(File.realpath(Dir.home), '.cache')
86
- end
87
- File.join(root, 'rubocop_cache')
77
+ CacheConfig.root_dir do
78
+ config_store.for_pwd.for_all_cops['CacheRootDirectory']
79
+ end
88
80
  end
89
81
 
90
82
  def self.allow_symlinks_in_cache_location?(config_store)
@@ -188,14 +180,24 @@ module RuboCop
188
180
  .select { |path| File.file?(path) }
189
181
  .sort!
190
182
  .each do |path|
191
- content = File.binread(path)
192
- digest << Zlib.crc32(content).to_s # mtime not reliable
183
+ digest << digest(path)
193
184
  end
194
185
  digest << RuboCop::Version::STRING << RuboCop::AST::Version::STRING
195
186
  digest.hexdigest
196
187
  end
197
188
  end
198
189
 
190
+ def digest(path)
191
+ content = if path.end_with?(*DL_EXTENSIONS)
192
+ # Shared libraries often contain timestamps of when
193
+ # they were compiled and other non-stable data.
194
+ File.basename(path)
195
+ else
196
+ File.binread(path) # mtime not reliable
197
+ end
198
+ Zlib.crc32(content).to_s
199
+ end
200
+
199
201
  def rubocop_extra_features
200
202
  lib_root = File.join(File.dirname(__FILE__), '..')
201
203
  exe_root = File.join(lib_root, '..', 'exe')
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'pathname'
4
+ require_relative '../cache_config'
5
+ require_relative '../config_finder'
4
6
 
5
7
  #
6
8
  # This code is based on https://github.com/fohte/rubocop-daemon.
@@ -19,6 +21,8 @@ module RuboCop
19
21
  GEMFILE_NAMES = %w[Gemfile gems.rb].freeze
20
22
 
21
23
  class << self
24
+ attr_accessor :cache_root_path
25
+
22
26
  # Searches for Gemfile or gems.rb in the current dir or any parent dirs
23
27
  def project_dir
24
28
  current_dir = Dir.pwd
@@ -38,12 +42,40 @@ module RuboCop
38
42
  end
39
43
 
40
44
  def dir
41
- cache_path = File.expand_path('~/.cache/rubocop_cache/server')
42
45
  Pathname.new(File.join(cache_path, project_dir_cache_key)).tap do |d|
43
46
  d.mkpath unless d.exist?
44
47
  end
45
48
  end
46
49
 
50
+ def cache_path
51
+ cache_root_dir = if cache_root_path
52
+ File.join(cache_root_path, 'rubocop_cache')
53
+ else
54
+ cache_root_dir_from_config
55
+ end
56
+
57
+ File.expand_path(File.join(cache_root_dir, 'server'))
58
+ end
59
+
60
+ def cache_root_dir_from_config
61
+ CacheConfig.root_dir do
62
+ # `RuboCop::ConfigStore` has heavy dependencies, this is a lightweight implementation
63
+ # so that only the necessary `CacheRootDirectory` can be obtained.
64
+ require 'yaml'
65
+
66
+ config_path = ConfigFinder.find_config_path(Dir.pwd)
67
+
68
+ # Ruby 3.1+
69
+ config_yaml = if Gem::Version.new(Psych::VERSION) >= Gem::Version.new('4.0.0')
70
+ YAML.safe_load_file(config_path, permitted_classes: [Regexp, Symbol])
71
+ else
72
+ YAML.load_file(config_path)
73
+ end
74
+
75
+ config_yaml.dig('AllCops', 'CacheRootDirectory')
76
+ end
77
+ end
78
+
47
79
  def port_path
48
80
  dir.join('port')
49
81
  end
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'optparse'
4
3
  require 'rainbow'
5
4
 
6
5
  #
@@ -30,6 +29,7 @@ module RuboCop
30
29
  @exit = false
31
30
  end
32
31
 
32
+ # rubocop:disable Metrics/MethodLength
33
33
  def run(argv = ARGV)
34
34
  unless Server.support_server?
35
35
  return error('RuboCop server is not supported by this Ruby.') if use_server_option?(argv)
@@ -37,6 +37,7 @@ module RuboCop
37
37
  return STATUS_SUCCESS
38
38
  end
39
39
 
40
+ Cache.cache_root_path = fetch_cache_root_path_from(argv)
40
41
  deleted_server_arguments = delete_server_argument_from(argv)
41
42
 
42
43
  if deleted_server_arguments.size >= 2
@@ -45,7 +46,7 @@ module RuboCop
45
46
 
46
47
  server_command = deleted_server_arguments.first
47
48
 
48
- if EXCLUSIVE_OPTIONS.include?(server_command) && argv.count >= 2
49
+ if EXCLUSIVE_OPTIONS.include?(server_command) && argv.count > allowed_option_count
49
50
  return error("#{server_command} cannot be combined with other options.")
50
51
  end
51
52
 
@@ -53,6 +54,7 @@ module RuboCop
53
54
 
54
55
  STATUS_SUCCESS
55
56
  end
57
+ # rubocop:enable Metrics/MethodLength
56
58
 
57
59
  def exit?
58
60
  @exit
@@ -83,6 +85,17 @@ module RuboCop
83
85
  end
84
86
  # rubocop:enable Metrics/CyclomaticComplexity, Metrics/MethodLength:
85
87
 
88
+ def fetch_cache_root_path_from(arguments)
89
+ cache_root = arguments.detect { |argument| argument.start_with?('--cache-root') }
90
+ return unless cache_root
91
+
92
+ if cache_root.start_with?('--cache-root=')
93
+ cache_root.split('=')[1]
94
+ else
95
+ arguments[arguments.index(cache_root) + 1]
96
+ end
97
+ end
98
+
86
99
  def delete_server_argument_from(all_arguments)
87
100
  SERVER_OPTIONS.each_with_object([]) do |server_option, server_arguments|
88
101
  server_arguments << all_arguments.delete(server_option)
@@ -93,6 +106,10 @@ module RuboCop
93
106
  (argv & SERVER_OPTIONS).any?
94
107
  end
95
108
 
109
+ def allowed_option_count
110
+ Cache.cache_root_path ? 2 : 1
111
+ end
112
+
96
113
  def error(message)
97
114
  @exit = true
98
115
  warn Rainbow(message).red
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  # This module holds the RuboCop version information.
5
5
  module Version
6
- STRING = '1.32.0'
6
+ STRING = '1.33.0'
7
7
 
8
8
  MSG = '%<version>s (using Parser %<parser_version>s, ' \
9
9
  'rubocop-ast %<rubocop_ast_version>s, ' \
data/lib/rubocop.rb CHANGED
@@ -86,7 +86,6 @@ require_relative 'rubocop/cop/mixin/gem_declaration'
86
86
  require_relative 'rubocop/cop/mixin/gemspec_help'
87
87
  require_relative 'rubocop/cop/mixin/hash_alignment_styles'
88
88
  require_relative 'rubocop/cop/mixin/hash_transform_method'
89
- require_relative 'rubocop/cop/mixin/ignored_methods'
90
89
  require_relative 'rubocop/cop/mixin/integer_node'
91
90
  require_relative 'rubocop/cop/mixin/interpolation'
92
91
  require_relative 'rubocop/cop/mixin/line_length_help'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubocop
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.32.0
4
+ version: 1.33.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bozhidar Batsov
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: exe
12
12
  cert_chain: []
13
- date: 2022-07-21 00:00:00.000000000 Z
13
+ date: 2022-08-04 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: json
@@ -208,6 +208,7 @@ files:
208
208
  - exe/rubocop
209
209
  - lib/rubocop.rb
210
210
  - lib/rubocop/ast_aliases.rb
211
+ - lib/rubocop/cache_config.rb
211
212
  - lib/rubocop/cached_data.rb
212
213
  - lib/rubocop/cli.rb
213
214
  - lib/rubocop/cli/command.rb
@@ -222,6 +223,7 @@ files:
222
223
  - lib/rubocop/cli/environment.rb
223
224
  - lib/rubocop/comment_config.rb
224
225
  - lib/rubocop/config.rb
226
+ - lib/rubocop/config_finder.rb
225
227
  - lib/rubocop/config_loader.rb
226
228
  - lib/rubocop/config_loader_resolver.rb
227
229
  - lib/rubocop/config_obsoletion.rb
@@ -581,7 +583,6 @@ files:
581
583
  - lib/rubocop/cop/mixin/hash_shorthand_syntax.rb
582
584
  - lib/rubocop/cop/mixin/hash_transform_method.rb
583
585
  - lib/rubocop/cop/mixin/heredoc.rb
584
- - lib/rubocop/cop/mixin/ignored_methods.rb
585
586
  - lib/rubocop/cop/mixin/integer_node.rb
586
587
  - lib/rubocop/cop/mixin/interpolation.rb
587
588
  - lib/rubocop/cop/mixin/line_length_help.rb
@@ -971,7 +972,7 @@ metadata:
971
972
  homepage_uri: https://rubocop.org/
972
973
  changelog_uri: https://github.com/rubocop/rubocop/blob/master/CHANGELOG.md
973
974
  source_code_uri: https://github.com/rubocop/rubocop/
974
- documentation_uri: https://docs.rubocop.org/rubocop/1.32/
975
+ documentation_uri: https://docs.rubocop.org/rubocop/1.33/
975
976
  bug_tracker_uri: https://github.com/rubocop/rubocop/issues
976
977
  rubygems_mfa_required: 'true'
977
978
  post_install_message: