rubocop 1.32.0 → 1.33.0

Sign up to get free protection for your applications and to get access to all the features.
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: