rubocop 1.72.2 → 1.73.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 (39) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -3
  3. data/config/default.yml +21 -11
  4. data/config/internal_affairs.yml +16 -0
  5. data/lib/rubocop/config_loader_resolver.rb +2 -2
  6. data/lib/rubocop/config_validator.rb +1 -1
  7. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +26 -1
  8. data/lib/rubocop/cop/layout/line_length.rb +3 -3
  9. data/lib/rubocop/cop/lint/duplicate_methods.rb +0 -14
  10. data/lib/rubocop/cop/lint/float_comparison.rb +1 -6
  11. data/lib/rubocop/cop/lint/literal_as_condition.rb +104 -7
  12. data/lib/rubocop/cop/lint/mixed_case_range.rb +1 -1
  13. data/lib/rubocop/cop/lint/redundant_require_statement.rb +0 -21
  14. data/lib/rubocop/cop/lint/redundant_type_conversion.rb +23 -2
  15. data/lib/rubocop/cop/lint/void.rb +6 -0
  16. data/lib/rubocop/cop/mixin/hash_subset.rb +19 -4
  17. data/lib/rubocop/cop/mixin/trailing_comma.rb +12 -0
  18. data/lib/rubocop/cop/naming/variable_name.rb +64 -6
  19. data/lib/rubocop/cop/style/accessor_grouping.rb +19 -5
  20. data/lib/rubocop/cop/style/endless_method.rb +163 -18
  21. data/lib/rubocop/cop/style/line_end_concatenation.rb +10 -4
  22. data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +1 -1
  23. data/lib/rubocop/cop/style/redundant_condition.rb +34 -0
  24. data/lib/rubocop/cop/style/redundant_format.rb +23 -11
  25. data/lib/rubocop/cop/style/redundant_self_assignment.rb +1 -1
  26. data/lib/rubocop/cop/style/single_line_methods.rb +3 -3
  27. data/lib/rubocop/cop/style/string_concatenation.rb +1 -1
  28. data/lib/rubocop/cop/style/trailing_comma_in_array_literal.rb +47 -6
  29. data/lib/rubocop/cop/style/trailing_comma_in_hash_literal.rb +48 -6
  30. data/lib/rubocop/cop/style/trivial_accessors.rb +1 -1
  31. data/lib/rubocop/cops_documentation_generator.rb +12 -1
  32. data/lib/rubocop/plugin/load_error.rb +1 -1
  33. data/lib/rubocop/plugin.rb +9 -2
  34. data/lib/rubocop/rspec/shared_contexts.rb +15 -0
  35. data/lib/rubocop/rspec/support.rb +1 -0
  36. data/lib/rubocop/version.rb +1 -1
  37. data/lib/rubocop.rb +0 -1
  38. metadata +4 -5
  39. data/lib/rubocop/cop/utils/regexp_ranges.rb +0 -113
@@ -6,12 +6,13 @@ module RuboCop
6
6
  # Checks for trailing comma in array literals.
7
7
  # The configuration options are:
8
8
  #
9
- # * `consistent_comma`: Requires a comma after the
10
- # last item of all non-empty, multiline array literals.
11
- # * `comma`: Requires a comma after last item in an array,
12
- # but only when each item is on its own line.
13
- # * `no_comma`: Does not require a comma after the
14
- # last item in an array
9
+ # * `consistent_comma`: Requires a comma after the last item of all non-empty, multiline array
10
+ # literals.
11
+ # * `comma`: Requires a comma after the last item in an array, but only when each item is on
12
+ # its own line.
13
+ # * `diff_comma`: Requires a comma after the last item in an array, but only when that item is
14
+ # followed by an immediate newline.
15
+ # * `no_comma`: Does not require a comma after the last item in an array
15
16
  #
16
17
  # @example EnforcedStyleForMultiline: consistent_comma
17
18
  # # bad
@@ -37,6 +38,14 @@ module RuboCop
37
38
  # 2,
38
39
  # ]
39
40
  #
41
+ # # bad
42
+ # a = [1, 2,
43
+ # 3, 4]
44
+ #
45
+ # # good
46
+ # a = [1, 2,
47
+ # 3, 4,]
48
+ #
40
49
  # @example EnforcedStyleForMultiline: comma
41
50
  # # bad
42
51
  # a = [1, 2,]
@@ -72,6 +81,38 @@ module RuboCop
72
81
  # 2,
73
82
  # ]
74
83
  #
84
+ # @example EnforcedStyleForMultiline: diff_comma
85
+ # # bad
86
+ # a = [1, 2,]
87
+ #
88
+ # # good
89
+ # a = [1, 2]
90
+ #
91
+ # # good
92
+ # a = [
93
+ # 1, 2,
94
+ # 3,
95
+ # ]
96
+ #
97
+ # # good
98
+ # a = [
99
+ # 1, 2, 3,
100
+ # ]
101
+ #
102
+ # # good
103
+ # a = [
104
+ # 1,
105
+ # 2,
106
+ # ]
107
+ #
108
+ # # bad
109
+ # a = [1, 2,
110
+ # 3, 4,]
111
+ #
112
+ # # good
113
+ # a = [1, 2,
114
+ # 3, 4]
115
+ #
75
116
  # @example EnforcedStyleForMultiline: no_comma (default)
76
117
  # # bad
77
118
  # a = [1, 2,]
@@ -6,12 +6,13 @@ module RuboCop
6
6
  # Checks for trailing comma in hash literals.
7
7
  # The configuration options are:
8
8
  #
9
- # * `consistent_comma`: Requires a comma after the
10
- # last item of all non-empty, multiline hash literals.
11
- # * `comma`: Requires a comma after the last item in a hash,
12
- # but only when each item is on its own line.
13
- # * `no_comma`: Does not require a comma after the
14
- # last item in a hash
9
+ # * `consistent_comma`: Requires a comma after the last item of all non-empty, multiline hash
10
+ # literals.
11
+ # * `comma`: Requires a comma after the last item in a hash, but only when each item is on its
12
+ # own line.
13
+ # * `diff_comma`: Requires a comma after the last item in a hash, but only when that item is
14
+ # followed by an immediate newline.
15
+ # * `no_comma`: Does not require a comma after the last item in a hash
15
16
  #
16
17
  # @example EnforcedStyleForMultiline: consistent_comma
17
18
  #
@@ -38,6 +39,14 @@ module RuboCop
38
39
  # bar: 2,
39
40
  # }
40
41
  #
42
+ # # bad
43
+ # a = { foo: 1, bar: 2,
44
+ # baz: 3, qux: 4 }
45
+ #
46
+ # # good
47
+ # a = { foo: 1, bar: 2,
48
+ # baz: 3, qux: 4, }
49
+ #
41
50
  # @example EnforcedStyleForMultiline: comma
42
51
  #
43
52
  # # bad
@@ -74,6 +83,39 @@ module RuboCop
74
83
  # bar: 2,
75
84
  # }
76
85
  #
86
+ # @example EnforcedStyleForMultiline: diff_comma
87
+ #
88
+ # # bad
89
+ # a = { foo: 1, bar: 2, }
90
+ #
91
+ # # good
92
+ # a = { foo: 1, bar: 2 }
93
+ #
94
+ # # good
95
+ # a = {
96
+ # foo: 1, bar: 2,
97
+ # qux: 3,
98
+ # }
99
+ #
100
+ # # good
101
+ # a = {
102
+ # foo: 1, bar: 2, qux: 3,
103
+ # }
104
+ #
105
+ # # good
106
+ # a = {
107
+ # foo: 1,
108
+ # bar: 2,
109
+ # }
110
+ #
111
+ # # bad
112
+ # a = { foo: 1, bar: 2,
113
+ # baz: 3, qux: 4, }
114
+ #
115
+ # # good
116
+ # a = { foo: 1, bar: 2,
117
+ # baz: 3, qux: 4 }
118
+ #
77
119
  # @example EnforcedStyleForMultiline: no_comma (default)
78
120
  #
79
121
  # # bad
@@ -113,7 +113,7 @@ module RuboCop
113
113
  private
114
114
 
115
115
  def in_module_or_instance_eval?(node)
116
- node.each_ancestor(:block, :class, :sclass, :module).each do |pnode|
116
+ node.each_ancestor(:any_block, :class, :sclass, :module).each do |pnode|
117
117
  case pnode.type
118
118
  when :class, :sclass
119
119
  return false
@@ -28,6 +28,12 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
28
28
  #
29
29
  # CopsDocumentationGenerator.new(departments: ['Lint']).call
30
30
  #
31
+ # For plugin extensions, specify `:plugin_name` keyword as follows:
32
+ #
33
+ # CopsDocumentationGenerator.new(
34
+ # departments: ['Performance'], plugin_name: 'rubocop-performance'
35
+ # ).call
36
+ #
31
37
  # You can append additional information:
32
38
  #
33
39
  # callback = ->(data) { required_rails_version(data.cop) }
@@ -36,11 +42,16 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
36
42
  # This will insert the string returned from the lambda _after_ the section from RuboCop itself.
37
43
  # See `CopsDocumentationGenerator::STRUCTURE` for available sections.
38
44
  #
39
- def initialize(departments: [], extra_info: {}, base_dir: Dir.pwd)
45
+ def initialize(departments: [], extra_info: {}, base_dir: Dir.pwd, plugin_name: nil)
40
46
  @departments = departments.map(&:to_sym).sort!
41
47
  @extra_info = extra_info
42
48
  @cops = RuboCop::Cop::Registry.global
43
49
  @config = RuboCop::ConfigLoader.default_configuration
50
+ # NOTE: For example, this prevents excessive plugin loading before another task executes,
51
+ # in cases where plugins are already loaded by `internal_investigation`.
52
+ if plugin_name && @config.loaded_plugins.none? { |plugin| plugin.about.name == plugin_name }
53
+ RuboCop::Plugin.integrate_plugins(RuboCop::Config.new, [plugin_name])
54
+ end
44
55
  @base_dir = base_dir
45
56
  @docs_path = "#{base_dir}/docs/modules/ROOT"
46
57
  FileUtils.mkdir_p("#{@docs_path}/pages")
@@ -15,7 +15,7 @@ module RuboCop
15
15
  <<~MESSAGE
16
16
  Failed to load plugin `#{@plugin_name}` because the corresponding plugin class could not be determined for instantiation.
17
17
  Try upgrading it first (e.g., `bundle update #{@plugin_name}`).
18
- If `#{@plugin_name}` is not yet a plugin, use `require: #{@plugin_name}` instead of `plugins: `#{@plugin_name}` in your configuration.
18
+ If `#{@plugin_name}` is not yet a plugin, use `require: #{@plugin_name}` instead of `plugins: #{@plugin_name}` in your configuration.
19
19
 
20
20
  For further assistance, check with the developer regarding the following points:
21
21
  https://docs.rubocop.org/rubocop/plugin_migration_guide.html
@@ -22,9 +22,16 @@ module RuboCop
22
22
  def plugin_capable?(feature_name)
23
23
  return true if BUILTIN_INTERNAL_PLUGINS.key?(feature_name)
24
24
  return true if feature_name == OBSOLETE_INTERNAL_AFFAIRS_PLUGIN_NAME
25
- return false unless (gem = Gem.loaded_specs[feature_name])
26
25
 
27
- !!gem.metadata['default_lint_roller_plugin']
26
+ begin
27
+ # When not using Bundler. Makes the spec available but does not require it.
28
+ gem feature_name
29
+ rescue Gem::LoadError
30
+ # The user requested a gem that they do not have installed
31
+ end
32
+ return false unless (spec = Gem.loaded_specs[feature_name])
33
+
34
+ !!spec.metadata['default_lint_roller_plugin']
28
35
  end
29
36
 
30
37
  def integrate_plugins(rubocop_config, plugins)
@@ -80,6 +80,21 @@ RSpec.shared_context 'maintain registry' do
80
80
  end
81
81
  end
82
82
 
83
+ RSpec.shared_context 'maintain default configuration' do
84
+ around(:each) do |example|
85
+ # Make a copy of the current configuration that will not change when source hash changes
86
+ default_configuration = RuboCop::ConfigLoader.default_configuration
87
+ config = RuboCop::Config.create(
88
+ default_configuration.to_h.clone,
89
+ default_configuration.loaded_path
90
+ )
91
+
92
+ example.run
93
+
94
+ RuboCop::ConfigLoader.instance_variable_set(:@default_configuration, config)
95
+ end
96
+ end
97
+
83
98
  # This context assumes nothing and defines `cop`, among others.
84
99
  RSpec.shared_context 'config' do # rubocop:disable Metrics/BlockLength
85
100
  ### Meant to be overridden at will
@@ -15,6 +15,7 @@ RSpec.configure do |config|
15
15
  config.include_context 'isolated bundler', :isolated_bundler
16
16
  config.include_context 'lsp', :lsp
17
17
  config.include_context 'maintain registry', :restore_registry
18
+ config.include_context 'maintain default configuration', :restore_configuration
18
19
  config.include_context 'ruby 2.0', :ruby20
19
20
  config.include_context 'ruby 2.1', :ruby21
20
21
  config.include_context 'ruby 2.2', :ruby22
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  # This module holds the RuboCop version information.
5
5
  module Version
6
- STRING = '1.72.2'
6
+ STRING = '1.73.0'
7
7
 
8
8
  MSG = '%<version>s (using %<parser_version>s, ' \
9
9
  'rubocop-ast %<rubocop_ast_version>s, ' \
data/lib/rubocop.rb CHANGED
@@ -148,7 +148,6 @@ require_relative 'rubocop/cop/mixin/comments_help' # relies on visibility_help
148
148
  require_relative 'rubocop/cop/mixin/def_node' # relies on visibility_help
149
149
 
150
150
  require_relative 'rubocop/cop/utils/format_string'
151
- require_relative 'rubocop/cop/utils/regexp_ranges'
152
151
 
153
152
  require_relative 'rubocop/cop/migration/department_name'
154
153
 
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.72.2
4
+ version: 1.73.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bozhidar Batsov
@@ -9,7 +9,7 @@ authors:
9
9
  - Yuji Nakayama
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2025-02-17 00:00:00.000000000 Z
12
+ date: 2025-02-26 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: json
@@ -971,7 +971,6 @@ files:
971
971
  - lib/rubocop/cop/team.rb
972
972
  - lib/rubocop/cop/util.rb
973
973
  - lib/rubocop/cop/utils/format_string.rb
974
- - lib/rubocop/cop/utils/regexp_ranges.rb
975
974
  - lib/rubocop/cop/variable_force.rb
976
975
  - lib/rubocop/cop/variable_force/assignment.rb
977
976
  - lib/rubocop/cop/variable_force/branch.rb
@@ -1075,9 +1074,9 @@ licenses:
1075
1074
  - MIT
1076
1075
  metadata:
1077
1076
  homepage_uri: https://rubocop.org/
1078
- changelog_uri: https://github.com/rubocop/rubocop/releases/tag/v1.72.2
1077
+ changelog_uri: https://github.com/rubocop/rubocop/releases/tag/v1.73.0
1079
1078
  source_code_uri: https://github.com/rubocop/rubocop/
1080
- documentation_uri: https://docs.rubocop.org/rubocop/1.72/
1079
+ documentation_uri: https://docs.rubocop.org/rubocop/1.73/
1081
1080
  bug_tracker_uri: https://github.com/rubocop/rubocop/issues
1082
1081
  rubygems_mfa_required: 'true'
1083
1082
  rdoc_options: []
@@ -1,113 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RuboCop
4
- module Cop
5
- module Utils
6
- # Helper to abstract complexity of building range pairs
7
- # with octal escape reconstruction (needed for regexp_parser < 2.7).
8
- class RegexpRanges
9
- attr_reader :root
10
-
11
- def initialize(root)
12
- @root = root
13
- @compound_token = []
14
- @pairs = []
15
- @populated = false
16
- end
17
-
18
- def compound_token
19
- populate_all unless @populated
20
-
21
- @compound_token
22
- end
23
-
24
- def pairs
25
- populate_all unless @populated
26
-
27
- @pairs
28
- end
29
-
30
- private
31
-
32
- def populate_all
33
- populate(@root)
34
-
35
- # If either bound is a compound the first one is an escape
36
- # and that's all we need to work with.
37
- # If there are any cops that wanted to operate on the compound
38
- # expression we could wrap it with a facade class.
39
- @pairs.map! { |pair| pair.map(&:first) }
40
-
41
- @populated = true
42
- end
43
-
44
- def populate(expr)
45
- expressions = expr.expressions.to_a
46
-
47
- until expressions.empty?
48
- current = expressions.shift
49
-
50
- if escaped_octal?(current)
51
- @compound_token << current
52
- @compound_token.concat(pop_octal_digits(expressions))
53
- # If we have all the digits we can discard.
54
- end
55
-
56
- next unless current.type == :set
57
-
58
- process_set(expressions, current)
59
- @compound_token.clear
60
- end
61
- end
62
-
63
- def process_set(expressions, current)
64
- case current.token
65
- when :range
66
- @pairs << compose_range(expressions, current)
67
- when :character
68
- # Child expressions may include the range we are looking for.
69
- populate(current)
70
- when :intersection
71
- # Each child expression could have child expressions that lead to ranges.
72
- current.expressions.each do |intersected|
73
- populate(intersected)
74
- end
75
- end
76
- end
77
-
78
- def compose_range(expressions, current)
79
- range_start, range_end = current.expressions
80
- range_start = if @compound_token.size.between?(1, 2) && octal_digit?(range_start.text)
81
- @compound_token.dup << range_start
82
- else
83
- [range_start]
84
- end
85
- range_end = [range_end]
86
- range_end.concat(pop_octal_digits(expressions)) if escaped_octal?(range_end.first)
87
- [range_start, range_end]
88
- end
89
-
90
- def escaped_octal?(expr)
91
- expr.text.valid_encoding? && expr.text =~ /^\\[0-7]$/
92
- end
93
-
94
- def octal_digit?(char)
95
- ('0'..'7').cover?(char)
96
- end
97
-
98
- def pop_octal_digits(expressions)
99
- digits = []
100
-
101
- 2.times do
102
- next unless (next_child = expressions.first)
103
- next unless next_child.type == :literal && next_child.text =~ /^[0-7]$/
104
-
105
- digits << expressions.shift
106
- end
107
-
108
- digits
109
- end
110
- end
111
- end
112
- end
113
- end