rubocop 0.87.1 → 0.88.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 (60) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/bin/rubocop-profile +31 -0
  4. data/config/default.yml +57 -6
  5. data/lib/rubocop.rb +6 -0
  6. data/lib/rubocop/cli.rb +2 -2
  7. data/lib/rubocop/cli/command/auto_genenerate_config.rb +2 -2
  8. data/lib/rubocop/config_loader.rb +20 -7
  9. data/lib/rubocop/config_store.rb +4 -0
  10. data/lib/rubocop/cop/autocorrect_logic.rb +1 -1
  11. data/lib/rubocop/cop/badge.rb +1 -1
  12. data/lib/rubocop/cop/base.rb +12 -4
  13. data/lib/rubocop/cop/cop.rb +1 -1
  14. data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +26 -0
  15. data/lib/rubocop/cop/gemspec/required_ruby_version.rb +6 -1
  16. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +1 -0
  17. data/lib/rubocop/cop/layout/end_alignment.rb +3 -2
  18. data/lib/rubocop/cop/layout/multiline_block_layout.rb +16 -5
  19. data/lib/rubocop/cop/layout/space_around_block_parameters.rb +3 -2
  20. data/lib/rubocop/cop/layout/space_around_method_call_operator.rb +27 -68
  21. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +3 -2
  22. data/lib/rubocop/cop/lint/disjunctive_assignment_in_constructor.rb +8 -2
  23. data/lib/rubocop/cop/lint/duplicate_elsif_condition.rb +39 -0
  24. data/lib/rubocop/cop/lint/duplicate_methods.rb +2 -2
  25. data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +3 -2
  26. data/lib/rubocop/cop/lint/literal_as_condition.rb +11 -1
  27. data/lib/rubocop/cop/lint/nested_method_definition.rb +13 -19
  28. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +67 -0
  29. data/lib/rubocop/cop/mixin/statement_modifier.rb +3 -3
  30. data/lib/rubocop/cop/style/accessor_grouping.rb +8 -1
  31. data/lib/rubocop/cop/style/array_coercion.rb +63 -0
  32. data/lib/rubocop/cop/style/auto_resource_cleanup.rb +3 -2
  33. data/lib/rubocop/cop/style/bisected_attr_accessor.rb +5 -4
  34. data/lib/rubocop/cop/style/case_like_if.rb +217 -0
  35. data/lib/rubocop/cop/style/commented_keyword.rb +5 -2
  36. data/lib/rubocop/cop/style/conditional_assignment.rb +1 -1
  37. data/lib/rubocop/cop/style/exponential_notation.rb +6 -8
  38. data/lib/rubocop/cop/style/float_division.rb +7 -10
  39. data/lib/rubocop/cop/style/format_string_token.rb +5 -5
  40. data/lib/rubocop/cop/style/hash_as_last_array_item.rb +62 -0
  41. data/lib/rubocop/cop/style/hash_like_case.rb +76 -0
  42. data/lib/rubocop/cop/style/if_unless_modifier.rb +11 -11
  43. data/lib/rubocop/cop/style/missing_else.rb +1 -11
  44. data/lib/rubocop/cop/style/numeric_predicate.rb +3 -4
  45. data/lib/rubocop/cop/style/parallel_assignment.rb +3 -3
  46. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +1 -1
  47. data/lib/rubocop/cop/style/redundant_file_extension_in_require.rb +50 -0
  48. data/lib/rubocop/cop/style/redundant_sort.rb +3 -2
  49. data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +3 -2
  50. data/lib/rubocop/cop/style/trailing_method_end_statement.rb +9 -32
  51. data/lib/rubocop/cop/variable_force/variable.rb +5 -3
  52. data/lib/rubocop/file_finder.rb +12 -12
  53. data/lib/rubocop/path_util.rb +2 -17
  54. data/lib/rubocop/result_cache.rb +12 -8
  55. data/lib/rubocop/rspec/expect_offense.rb +31 -5
  56. data/lib/rubocop/rspec/shared_contexts.rb +12 -9
  57. data/lib/rubocop/runner.rb +5 -6
  58. data/lib/rubocop/target_finder.rb +2 -2
  59. data/lib/rubocop/version.rb +1 -1
  60. metadata +9 -2
@@ -5,7 +5,7 @@ module RuboCop
5
5
  module PathUtil
6
6
  module_function
7
7
 
8
- def relative_path(path, base_dir = PathUtil.pwd)
8
+ def relative_path(path, base_dir = Dir.pwd)
9
9
  # Optimization for the common case where path begins with the base
10
10
  # dir. Just cut off the first part.
11
11
  if path.start_with?(base_dir)
@@ -24,7 +24,7 @@ module RuboCop
24
24
 
25
25
  def smart_path(path)
26
26
  # Ideally, we calculate this relative to the project root.
27
- base_dir = PathUtil.pwd
27
+ base_dir = Dir.pwd
28
28
 
29
29
  if path.start_with? base_dir
30
30
  relative_path(path, base_dir)
@@ -54,21 +54,6 @@ module RuboCop
54
54
  %r{\A([A-Z]:)?/}i.match?(path)
55
55
  end
56
56
 
57
- def self.pwd
58
- @pwd ||= Dir.pwd
59
- end
60
-
61
- def self.reset_pwd
62
- @pwd = nil
63
- end
64
-
65
- def self.chdir(dir, &block)
66
- reset_pwd
67
- Dir.chdir(dir, &block)
68
- ensure
69
- reset_pwd
70
- end
71
-
72
57
  def hidden_file_in_not_hidden_dir?(pattern, path)
73
58
  File.fnmatch?(
74
59
  pattern, path,
@@ -33,7 +33,7 @@ module RuboCop
33
33
 
34
34
  def requires_file_removal?(file_count, config_store)
35
35
  file_count > 1 &&
36
- file_count > config_store.for_dir('.').for_all_cops['MaxFilesInCache']
36
+ file_count > config_store.for_pwd.for_all_cops['MaxFilesInCache']
37
37
  end
38
38
 
39
39
  def remove_oldest_files(files, dirs, cache_root, verbose)
@@ -60,7 +60,7 @@ module RuboCop
60
60
  end
61
61
 
62
62
  def self.cache_root(config_store)
63
- root = config_store.for_dir('.').for_all_cops['CacheRootDirectory']
63
+ root = config_store.for_pwd.for_all_cops['CacheRootDirectory']
64
64
  root ||= if ENV.key?('XDG_CACHE_HOME')
65
65
  # Include user ID in the path to make sure the user has write
66
66
  # access.
@@ -72,7 +72,7 @@ module RuboCop
72
72
  end
73
73
 
74
74
  def self.allow_symlinks_in_cache_location?(config_store)
75
- config_store.for_dir('.').for_all_cops['AllowSymlinksInCacheRootDirectory']
75
+ config_store.for_pwd.for_all_cops['AllowSymlinksInCacheRootDirectory']
76
76
  end
77
77
 
78
78
  def initialize(file, team, options, config_store, cache_root = nil)
@@ -158,6 +158,7 @@ module RuboCop
158
158
  end
159
159
 
160
160
  # The checksum of the rubocop program running the inspection.
161
+ # rubocop:disable Metrics/AbcSize
161
162
  def rubocop_checksum
162
163
  ResultCache.source_checksum ||=
163
164
  begin
@@ -168,13 +169,16 @@ module RuboCop
168
169
  # exe directory. A change to any of them could affect the cop output
169
170
  # so we include them in the cache hash.
170
171
  source_files = $LOADED_FEATURES + Find.find(exe_root).to_a
171
- sources = source_files
172
- .select { |path| File.file?(path) }
173
- .sort
174
- .map { |path| IO.read(path, encoding: Encoding::UTF_8) }
175
- Digest::SHA1.hexdigest(sources.join)
172
+
173
+ digest = Digest::SHA1.new
174
+ source_files
175
+ .select { |path| File.file?(path) }
176
+ .sort!
177
+ .each { |path| digest << File.mtime(path).to_s }
178
+ digest.hexdigest
176
179
  end
177
180
  end
181
+ # rubocop:enable Metrics/AbcSize
178
182
 
179
183
  # Return a hash of the options given at invocation, minus the ones that have
180
184
  # no effect on which offenses and disabled line ranges are found, and thus
@@ -73,19 +73,20 @@ module RuboCop
73
73
  # expect_no_corrections
74
74
  #
75
75
  # If your code has variables of different lengths, you can use `%{foo}`,
76
- # `^{foo}`, and `_{foo}` to format your template:
76
+ # `^{foo}`, and `_{foo}` to format your template; you can also abbreviate
77
+ # offense messages with `[...]`:
77
78
  #
78
79
  # %w[raise fail].each do |keyword|
79
80
  # expect_offense(<<~RUBY, keyword: keyword)
80
81
  # %{keyword}(RuntimeError, msg)
81
- # ^{keyword}^^^^^^^^^^^^^^^^^^^ Redundant `RuntimeError` argument can be removed.
82
+ # ^{keyword}^^^^^^^^^^^^^^^^^^^ Redundant `RuntimeError` argument [...]
82
83
  # RUBY
83
84
  #
84
85
  # %w[has_one has_many].each do |type|
85
86
  # expect_offense(<<~RUBY, type: type)
86
87
  # class Book
87
88
  # %{type} :chapter, foreign_key: 'book_id'
88
- # _{type} ^^^^^^^^^^^^^^^^^^^^^^ Specifying the default value is redundant.
89
+ # _{type} ^^^^^^^^^^^^^^^^^^^^^^ Specifying the default [...]
89
90
  # end
90
91
  # RUBY
91
92
  # end
@@ -102,6 +103,7 @@ module RuboCop
102
103
  module ExpectOffense
103
104
  def format_offense(source, **replacements)
104
105
  replacements.each do |keyword, value|
106
+ value = value.to_s
105
107
  source = source.gsub("%{#{keyword}}", value)
106
108
  .gsub("^{#{keyword}}", '^' * value.size)
107
109
  .gsub("_{#{keyword}}", ' ' * value.size)
@@ -132,7 +134,7 @@ module RuboCop
132
134
  actual_annotations =
133
135
  expected_annotations.with_offense_annotations(offenses)
134
136
 
135
- expect(actual_annotations.to_s).to eq(expected_annotations.to_s)
137
+ expect(actual_annotations).to eq(expected_annotations)
136
138
  expect(offenses.map(&:severity).uniq).to eq([severity]) if severity
137
139
  end
138
140
 
@@ -188,6 +190,7 @@ module RuboCop
188
190
  # Parsed representation of code annotated with the `^^^ Message` style
189
191
  class AnnotatedSource
190
192
  ANNOTATION_PATTERN = /\A\s*(\^+|\^{}) /.freeze
193
+ ABBREV = "[...]\n"
191
194
 
192
195
  # @param annotated_source [String] string passed to the matchers
193
196
  #
@@ -206,6 +209,7 @@ module RuboCop
206
209
  source << source_line
207
210
  end
208
211
  end
212
+ annotations.each { |a| a[0] = 1 } if source.empty?
209
213
 
210
214
  new(source, annotations)
211
215
  end
@@ -221,6 +225,27 @@ module RuboCop
221
225
  @annotations = annotations.sort.freeze
222
226
  end
223
227
 
228
+ def ==(other)
229
+ other.is_a?(self.class) &&
230
+ other.lines == lines &&
231
+ match_annotations?(other)
232
+ end
233
+
234
+ # Dirty hack: expectations with [...] are rewritten when they match
235
+ # This way the diff is clean.
236
+ def match_annotations?(other)
237
+ annotations.zip(other.annotations) do |(_actual_line, actual_annotation),
238
+ (_expected_line, expected_annotation)|
239
+ if expected_annotation&.end_with?(ABBREV)
240
+ if actual_annotation.start_with?(expected_annotation[0...-ABBREV.length])
241
+ expected_annotation.replace(actual_annotation)
242
+ end
243
+ end
244
+ end
245
+
246
+ annotations == other.annotations
247
+ end
248
+
224
249
  # Construct annotated source string (like what we parse)
225
250
  #
226
251
  # Reconstruct a deterministic annotated source string. This is
@@ -253,6 +278,7 @@ module RuboCop
253
278
 
254
279
  reconstructed.join
255
280
  end
281
+ alias inspect to_s
256
282
 
257
283
  # Return the plain source code without annotations
258
284
  #
@@ -279,7 +305,7 @@ module RuboCop
279
305
  self.class.new(lines, offense_annotations)
280
306
  end
281
307
 
282
- private
308
+ protected
283
309
 
284
310
  attr_reader :lines, :annotations
285
311
  end
@@ -12,19 +12,22 @@ RSpec.shared_context 'isolated environment', :isolated_environment do
12
12
  # get mismatched pathnames when loading config files later on.
13
13
  tmpdir = File.realpath(tmpdir)
14
14
 
15
+ virtual_home = File.expand_path(File.join(tmpdir, 'home'))
16
+ Dir.mkdir(virtual_home)
17
+ ENV['HOME'] = virtual_home
18
+ ENV.delete('XDG_CONFIG_HOME')
19
+
20
+ base_dir = example.metadata[:project_inside_home] ? virtual_home : tmpdir
21
+ root = example.metadata[:root]
22
+ working_dir = root ? File.join(base_dir, 'work', root) : File.join(base_dir, 'work')
23
+
15
24
  # Make upwards search for .rubocop.yml files stop at this directory.
16
- RuboCop::FileFinder.root_level = tmpdir
25
+ RuboCop::FileFinder.root_level = working_dir
17
26
 
18
27
  begin
19
- virtual_home = File.expand_path(File.join(tmpdir, 'home'))
20
- Dir.mkdir(virtual_home)
21
- ENV['HOME'] = virtual_home
22
- ENV.delete('XDG_CONFIG_HOME')
23
-
24
- working_dir = File.join(tmpdir, 'work')
25
- Dir.mkdir(working_dir)
28
+ FileUtils.mkdir_p(working_dir)
26
29
 
27
- RuboCop::PathUtil.chdir(working_dir) do
30
+ Dir.chdir(working_dir) do
28
31
  example.run
29
32
  end
30
33
  ensure
@@ -118,8 +118,7 @@ module RuboCop
118
118
 
119
119
  def file_offenses(file)
120
120
  file_offense_cache(file) do
121
- source = get_processed_source(file)
122
- source, offenses = do_inspection_loop(file, source)
121
+ source, offenses = do_inspection_loop(file)
123
122
  offenses = add_redundant_disables(file, offenses.compact.sort, source)
124
123
  offenses.sort.reject(&:disabled?).freeze
125
124
  end
@@ -159,8 +158,7 @@ module RuboCop
159
158
  # Do one extra inspection loop if any redundant disables were
160
159
  # removed. This is done in order to find rubocop:enable directives that
161
160
  # have now become useless.
162
- _source, new_offenses = do_inspection_loop(file,
163
- get_processed_source(file))
161
+ _source, new_offenses = do_inspection_loop(file)
164
162
  offenses |= new_offenses
165
163
  end
166
164
  end
@@ -213,7 +211,7 @@ module RuboCop
213
211
  @cached_run ||=
214
212
  (@options[:cache] == 'true' ||
215
213
  @options[:cache] != 'false' &&
216
- @config_store.for_dir(Dir.pwd).for_all_cops['UseCache']) &&
214
+ @config_store.for_pwd.for_all_cops['UseCache']) &&
217
215
  # When running --auto-gen-config, there's some processing done in the
218
216
  # cops related to calculating the Max parameters for Metrics cops. We
219
217
  # need to do that processing and cannot use caching.
@@ -232,7 +230,8 @@ module RuboCop
232
230
  cache.save(offenses)
233
231
  end
234
232
 
235
- def do_inspection_loop(file, processed_source)
233
+ def do_inspection_loop(file)
234
+ processed_source = get_processed_source(file)
236
235
  offenses = []
237
236
 
238
237
  # When running with --auto-correct, we need to inspect the file (which
@@ -132,7 +132,7 @@ module RuboCop
132
132
  end
133
133
 
134
134
  def all_cops_include
135
- @config_store.for('.').for_all_cops['Include'].map(&:to_s)
135
+ @config_store.for_pwd.for_all_cops['Include'].map(&:to_s)
136
136
  end
137
137
 
138
138
  def ruby_executable?(file)
@@ -160,7 +160,7 @@ module RuboCop
160
160
  end
161
161
 
162
162
  def configured_include?(file)
163
- @config_store.for('.').file_to_include?(file)
163
+ @config_store.for_pwd.file_to_include?(file)
164
164
  end
165
165
 
166
166
  def included_file?(file)
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  # This module holds the RuboCop version information.
5
5
  module Version
6
- STRING = '0.87.1'
6
+ STRING = '0.88.0'
7
7
 
8
8
  MSG = '%<version>s (using Parser %<parser_version>s, '\
9
9
  'rubocop-ast %<rubocop_ast_version>s, ' \
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: 0.87.1
4
+ version: 0.88.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: 2020-07-07 00:00:00.000000000 Z
13
+ date: 2020-07-13 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: parallel
@@ -178,6 +178,7 @@ files:
178
178
  - assets/logo.png
179
179
  - assets/output.html.erb
180
180
  - bin/console
181
+ - bin/rubocop-profile
181
182
  - bin/setup
182
183
  - config/default.yml
183
184
  - exe/rubocop
@@ -347,6 +348,7 @@ files:
347
348
  - lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb
348
349
  - lib/rubocop/cop/lint/disjunctive_assignment_in_constructor.rb
349
350
  - lib/rubocop/cop/lint/duplicate_case_condition.rb
351
+ - lib/rubocop/cop/lint/duplicate_elsif_condition.rb
350
352
  - lib/rubocop/cop/lint/duplicate_hash_key.rb
351
353
  - lib/rubocop/cop/lint/duplicate_methods.rb
352
354
  - lib/rubocop/cop/lint/each_with_object_argument.rb
@@ -529,6 +531,7 @@ files:
529
531
  - lib/rubocop/cop/style/accessor_grouping.rb
530
532
  - lib/rubocop/cop/style/alias.rb
531
533
  - lib/rubocop/cop/style/and_or.rb
534
+ - lib/rubocop/cop/style/array_coercion.rb
532
535
  - lib/rubocop/cop/style/array_join.rb
533
536
  - lib/rubocop/cop/style/ascii_comments.rb
534
537
  - lib/rubocop/cop/style/attr.rb
@@ -539,6 +542,7 @@ files:
539
542
  - lib/rubocop/cop/style/block_comments.rb
540
543
  - lib/rubocop/cop/style/block_delimiters.rb
541
544
  - lib/rubocop/cop/style/case_equality.rb
545
+ - lib/rubocop/cop/style/case_like_if.rb
542
546
  - lib/rubocop/cop/style/character_literal.rb
543
547
  - lib/rubocop/cop/style/class_and_module_children.rb
544
548
  - lib/rubocop/cop/style/class_check.rb
@@ -582,7 +586,9 @@ files:
582
586
  - lib/rubocop/cop/style/frozen_string_literal_comment.rb
583
587
  - lib/rubocop/cop/style/global_vars.rb
584
588
  - lib/rubocop/cop/style/guard_clause.rb
589
+ - lib/rubocop/cop/style/hash_as_last_array_item.rb
585
590
  - lib/rubocop/cop/style/hash_each_methods.rb
591
+ - lib/rubocop/cop/style/hash_like_case.rb
586
592
  - lib/rubocop/cop/style/hash_syntax.rb
587
593
  - lib/rubocop/cop/style/hash_transform_keys.rb
588
594
  - lib/rubocop/cop/style/hash_transform_values.rb
@@ -654,6 +660,7 @@ files:
654
660
  - lib/rubocop/cop/style/redundant_conditional.rb
655
661
  - lib/rubocop/cop/style/redundant_exception.rb
656
662
  - lib/rubocop/cop/style/redundant_fetch_block.rb
663
+ - lib/rubocop/cop/style/redundant_file_extension_in_require.rb
657
664
  - lib/rubocop/cop/style/redundant_freeze.rb
658
665
  - lib/rubocop/cop/style/redundant_interpolation.rb
659
666
  - lib/rubocop/cop/style/redundant_parentheses.rb