rubocop 1.17.0 → 1.18.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +70 -29
  4. data/lib/rubocop.rb +2 -0
  5. data/lib/rubocop/cli/command/suggest_extensions.rb +3 -3
  6. data/lib/rubocop/config_loader.rb +1 -1
  7. data/lib/rubocop/config_loader_resolver.rb +1 -1
  8. data/lib/rubocop/config_validator.rb +23 -10
  9. data/lib/rubocop/cop/base.rb +2 -2
  10. data/lib/rubocop/cop/bundler/duplicated_gem.rb +1 -1
  11. data/lib/rubocop/cop/bundler/gem_version.rb +38 -4
  12. data/lib/rubocop/cop/corrector.rb +4 -4
  13. data/lib/rubocop/cop/generator.rb +1 -1
  14. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +1 -1
  15. data/lib/rubocop/cop/layout/argument_alignment.rb +1 -1
  16. data/lib/rubocop/cop/layout/array_alignment.rb +2 -2
  17. data/lib/rubocop/cop/layout/block_alignment.rb +1 -1
  18. data/lib/rubocop/cop/layout/class_structure.rb +5 -1
  19. data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +7 -1
  20. data/lib/rubocop/cop/layout/comment_indentation.rb +1 -1
  21. data/lib/rubocop/cop/layout/end_alignment.rb +8 -1
  22. data/lib/rubocop/cop/layout/first_argument_indentation.rb +1 -1
  23. data/lib/rubocop/cop/layout/first_array_element_indentation.rb +2 -2
  24. data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +2 -2
  25. data/lib/rubocop/cop/layout/first_parameter_indentation.rb +1 -1
  26. data/lib/rubocop/cop/layout/hash_alignment.rb +25 -24
  27. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +1 -1
  28. data/lib/rubocop/cop/layout/indentation_style.rb +2 -2
  29. data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +122 -0
  30. data/lib/rubocop/cop/layout/multiline_array_brace_layout.rb +6 -6
  31. data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +2 -2
  32. data/lib/rubocop/cop/layout/multiline_hash_brace_layout.rb +6 -6
  33. data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +6 -6
  34. data/lib/rubocop/cop/layout/multiline_method_definition_brace_layout.rb +6 -6
  35. data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +3 -3
  36. data/lib/rubocop/cop/layout/parameter_alignment.rb +2 -2
  37. data/lib/rubocop/cop/layout/space_around_operators.rb +5 -1
  38. data/lib/rubocop/cop/lint/duplicate_branch.rb +2 -1
  39. data/lib/rubocop/cop/lint/nested_percent_literal.rb +1 -1
  40. data/lib/rubocop/cop/lint/percent_string_array.rb +1 -1
  41. data/lib/rubocop/cop/lint/percent_symbol_array.rb +1 -1
  42. data/lib/rubocop/cop/lint/symbol_conversion.rb +1 -1
  43. data/lib/rubocop/cop/lint/unused_block_argument.rb +1 -1
  44. data/lib/rubocop/cop/lint/useless_assignment.rb +1 -1
  45. data/lib/rubocop/cop/lint/useless_times.rb +1 -1
  46. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +1 -1
  47. data/lib/rubocop/cop/mixin/check_line_breakable.rb +12 -3
  48. data/lib/rubocop/cop/mixin/hash_transform_method.rb +6 -1
  49. data/lib/rubocop/cop/naming/inclusive_language.rb +249 -0
  50. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +2 -2
  51. data/lib/rubocop/cop/style/block_delimiters.rb +15 -0
  52. data/lib/rubocop/cop/style/class_and_module_children.rb +14 -0
  53. data/lib/rubocop/cop/style/comment_annotation.rb +50 -6
  54. data/lib/rubocop/cop/style/double_cop_disable_directive.rb +1 -7
  55. data/lib/rubocop/cop/style/eval_with_location.rb +1 -1
  56. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +8 -2
  57. data/lib/rubocop/cop/style/hash_syntax.rb +1 -1
  58. data/lib/rubocop/cop/style/multiple_comparison.rb +1 -1
  59. data/lib/rubocop/cop/style/mutable_constant.rb +6 -8
  60. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +1 -1
  61. data/lib/rubocop/cop/style/quoted_symbols.rb +2 -2
  62. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +1 -1
  63. data/lib/rubocop/cop/style/regexp_literal.rb +3 -2
  64. data/lib/rubocop/cop/style/single_line_methods.rb +25 -15
  65. data/lib/rubocop/cop/style/special_global_vars.rb +3 -3
  66. data/lib/rubocop/cop/style/string_concatenation.rb +32 -5
  67. data/lib/rubocop/cop/style/string_literals.rb +2 -2
  68. data/lib/rubocop/cop/style/swap_values.rb +1 -1
  69. data/lib/rubocop/cop/style/unpack_first.rb +1 -1
  70. data/lib/rubocop/cop/variable_force/variable_table.rb +1 -1
  71. data/lib/rubocop/formatter/git_hub_actions_formatter.rb +1 -1
  72. data/lib/rubocop/options.rb +4 -4
  73. data/lib/rubocop/rspec/cop_helper.rb +1 -1
  74. data/lib/rubocop/rspec/expect_offense.rb +1 -1
  75. data/lib/rubocop/version.rb +1 -1
  76. metadata +11 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f038acc03307acfc14ddf1dd971bf78978fac3401b4588b78b6bab4f4b7d8e13
4
- data.tar.gz: 4f5da9053cce2f82b955f15d311d4b0d1f78396b2d49c8672c27d380804d5ba8
3
+ metadata.gz: ca5a85edf6c093ecee74e82617e0c618424e907cbb6a71fb1f996492073a98e4
4
+ data.tar.gz: 1ceb28336ce8913d79d4260000f5a86ca93190f5e36f6809d690aa20559674fa
5
5
  SHA512:
6
- metadata.gz: 6c4b743259b607ed588066f260b69cfdfd03772cd89f533eaf80705e689005a771ef76cf29873d73c0e5f97e3b7b4be6e6080a5890a63ebb19150d951ae272e1
7
- data.tar.gz: 7505601eb0e34cc563cb8b7efdec9b6340e709f6a29eec7a7b952f84386df60fe8912b8ebd0849d9ba59e22e7701b980276f8bd728330985d5fa9bdf99c2d9ad
6
+ metadata.gz: c020a6c2b13ad36e18afac1a2293f7c30fec5d2d62a36f5f7ffea8887816985ec27b94295fba1e08f9f1b7f462c8b4ca28a4949a32baadcea17e15ff4181b0e3
7
+ data.tar.gz: 06e9a6431dc25b8152b0b380d4de434409579fcb0b66da5335b434798889fd8f6d6a58064a044595b1a45b2bad7830e8045011c7e20e64f1337ccdd11a04e29c
data/README.md CHANGED
@@ -54,7 +54,7 @@ To prevent an unwanted RuboCop update you might want to use a conservative versi
54
54
  in your `Gemfile`:
55
55
 
56
56
  ```rb
57
- gem 'rubocop', '~> 1.17', require: false
57
+ gem 'rubocop', '~> 1.18', require: false
58
58
  ```
59
59
 
60
60
  See [our versioning policy](https://docs.rubocop.org/rubocop/versioning.html) for further details.
data/config/default.yml CHANGED
@@ -270,8 +270,8 @@ Layout/AccessModifierIndentation:
270
270
  SupportedStyles:
271
271
  - outdent
272
272
  - indent
273
- # By default, the indentation width from Layout/IndentationWidth is used
274
- # But it can be overridden by setting this parameter
273
+ # By default the indentation width from `Layout/IndentationWidth` is used,
274
+ # but it can be overridden by setting this parameter.
275
275
  IndentationWidth: ~
276
276
 
277
277
  Layout/ArgumentAlignment:
@@ -299,8 +299,8 @@ Layout/ArgumentAlignment:
299
299
  SupportedStyles:
300
300
  - with_first_argument
301
301
  - with_fixed_indentation
302
- # By default, the indentation width from Layout/IndentationWidth is used
303
- # But it can be overridden by setting this parameter
302
+ # By default the indentation width from `Layout/IndentationWidth` is used,
303
+ # but it can be overridden by setting this parameter.
304
304
  IndentationWidth: ~
305
305
 
306
306
  Layout/ArrayAlignment:
@@ -328,8 +328,8 @@ Layout/ArrayAlignment:
328
328
  SupportedStyles:
329
329
  - with_first_element
330
330
  - with_fixed_indentation
331
- # By default, the indentation width from Layout/IndentationWidth is used
332
- # But it can be overridden by setting this parameter
331
+ # By default the indentation width from `Layout/IndentationWidth` is used,
332
+ # but it can be overridden by setting this parameter.
333
333
  IndentationWidth: ~
334
334
 
335
335
  Layout/AssignmentIndentation:
@@ -339,8 +339,8 @@ Layout/AssignmentIndentation:
339
339
  Enabled: true
340
340
  VersionAdded: '0.49'
341
341
  VersionChanged: '0.77'
342
- # By default, the indentation width from `Layout/IndentationWidth` is used
343
- # But it can be overridden by setting this parameter
342
+ # By default the indentation width from `Layout/IndentationWidth` is used,
343
+ # but it can be overridden by setting this parameter.
344
344
  IndentationWidth: ~
345
345
 
346
346
  Layout/BeginEndAlignment:
@@ -387,9 +387,9 @@ Layout/CaseIndentation:
387
387
  - case
388
388
  - end
389
389
  IndentOneStep: false
390
- # By default, the indentation width from `Layout/IndentationWidth` is used.
391
- # But it can be overridden by setting this parameter.
392
- # This only matters if `IndentOneStep` is `true`
390
+ # By default the indentation width from `Layout/IndentationWidth` is used,
391
+ # but it can be overridden by setting this parameter.
392
+ # This only matters if `IndentOneStep` is `true`.
393
393
  IndentationWidth: ~
394
394
 
395
395
  Layout/ClassStructure:
@@ -666,8 +666,8 @@ Layout/FirstArgumentIndentation:
666
666
  # Same as `special_for_inner_method_call` except that the special rule only
667
667
  # applies if the outer method call encloses its arguments in parentheses.
668
668
  - special_for_inner_method_call_in_parentheses
669
- # By default, the indentation width from `Layout/IndentationWidth` is used
670
- # But it can be overridden by setting this parameter
669
+ # By default the indentation width from `Layout/IndentationWidth` is used,
670
+ # but it can be overridden by setting this parameter.
671
671
  IndentationWidth: ~
672
672
 
673
673
  Layout/FirstArrayElementIndentation:
@@ -693,8 +693,8 @@ Layout/FirstArrayElementIndentation:
693
693
  - special_inside_parentheses
694
694
  - consistent
695
695
  - align_brackets
696
- # By default, the indentation width from `Layout/IndentationWidth` is used
697
- # But it can be overridden by setting this parameter
696
+ # By default the indentation width from `Layout/IndentationWidth` is used,
697
+ # but it can be overridden by setting this parameter.
698
698
  IndentationWidth: ~
699
699
 
700
700
  Layout/FirstArrayElementLineBreak:
@@ -725,8 +725,8 @@ Layout/FirstHashElementIndentation:
725
725
  - special_inside_parentheses
726
726
  - consistent
727
727
  - align_braces
728
- # By default, the indentation width from `Layout/IndentationWidth` is used
729
- # But it can be overridden by setting this parameter
728
+ # By default the indentation width from `Layout/IndentationWidth` is used,
729
+ # but it can be overridden by setting this parameter.
730
730
  IndentationWidth: ~
731
731
 
732
732
  Layout/FirstHashElementLineBreak:
@@ -761,8 +761,8 @@ Layout/FirstParameterIndentation:
761
761
  SupportedStyles:
762
762
  - consistent
763
763
  - align_parentheses
764
- # By default, the indentation width from `Layout/IndentationWidth` is used
765
- # But it can be overridden by setting this parameter
764
+ # By default the indentation width from `Layout/IndentationWidth` is used,
765
+ # but it can be overridden by setting this parameter.
766
766
  IndentationWidth: ~
767
767
 
768
768
  Layout/HashAlignment:
@@ -883,8 +883,8 @@ Layout/IndentationStyle:
883
883
  Enabled: true
884
884
  VersionAdded: '0.49'
885
885
  VersionChanged: '0.82'
886
- # By default, the indentation width from Layout/IndentationWidth is used
887
- # But it can be overridden by setting this parameter
886
+ # By default the indentation width from `Layout/IndentationWidth` is used,
887
+ # but it can be overridden by setting this parameter.
888
888
  # It is used during auto-correction to determine how many spaces should
889
889
  # replace each tab.
890
890
  IndentationWidth: ~
@@ -923,6 +923,20 @@ Layout/LeadingEmptyLines:
923
923
  VersionAdded: '0.57'
924
924
  VersionChanged: '0.77'
925
925
 
926
+ Layout/LineEndStringConcatenationIndentation:
927
+ Description: >-
928
+ Checks the indentation of the next line after a line that
929
+ ends with a string literal and a backslash.
930
+ Enabled: pending
931
+ VersionAdded: '1.18'
932
+ EnforcedStyle: aligned
933
+ SupportedStyles:
934
+ - aligned
935
+ - indented
936
+ # By default the indentation width from `Layout/IndentationWidth` is used,
937
+ # but it can be overridden by setting this parameter.
938
+ IndentationWidth: ~
939
+
926
940
  Layout/LineLength:
927
941
  Description: 'Checks that line length does not exceed the configured limit.'
928
942
  StyleGuide: '#max-line-length'
@@ -1053,8 +1067,8 @@ Layout/MultilineMethodCallIndentation:
1053
1067
  - aligned
1054
1068
  - indented
1055
1069
  - indented_relative_to_receiver
1056
- # By default, the indentation width from Layout/IndentationWidth is used
1057
- # But it can be overridden by setting this parameter
1070
+ # By default the indentation width from `Layout/IndentationWidth` is used,
1071
+ # but it can be overridden by setting this parameter.
1058
1072
  IndentationWidth: ~
1059
1073
 
1060
1074
  Layout/MultilineMethodDefinitionBraceLayout:
@@ -1083,8 +1097,8 @@ Layout/MultilineOperationIndentation:
1083
1097
  SupportedStyles:
1084
1098
  - aligned
1085
1099
  - indented
1086
- # By default, the indentation width from `Layout/IndentationWidth` is used
1087
- # But it can be overridden by setting this parameter
1100
+ # By default the indentation width from `Layout/IndentationWidth` is used,
1101
+ # but it can be overridden by setting this parameter.
1088
1102
  IndentationWidth: ~
1089
1103
 
1090
1104
  Layout/ParameterAlignment:
@@ -1112,8 +1126,8 @@ Layout/ParameterAlignment:
1112
1126
  SupportedStyles:
1113
1127
  - with_first_parameter
1114
1128
  - with_fixed_indentation
1115
- # By default, the indentation width from Layout/IndentationWidth is used
1116
- # But it can be overridden by setting this parameter
1129
+ # By default the indentation width from `Layout/IndentationWidth` is used,
1130
+ # but it can be overridden by setting this parameter.
1117
1131
  IndentationWidth: ~
1118
1132
 
1119
1133
  Layout/RedundantLineBreak:
@@ -1795,7 +1809,7 @@ Lint/MissingCopEnableDirective:
1795
1809
  Lint/MissingSuper:
1796
1810
  Description: >-
1797
1811
  This cop checks for the presence of constructors and lifecycle callbacks
1798
- without calls to `super`'.
1812
+ without calls to `super`.
1799
1813
  Enabled: true
1800
1814
  VersionAdded: '0.89'
1801
1815
  VersionChanged: '1.4'
@@ -2520,6 +2534,31 @@ Naming/HeredocDelimiterNaming:
2520
2534
  ForbiddenDelimiters:
2521
2535
  - !ruby/regexp '/(^|\s)(EO[A-Z]{1}|END)(\s|$)/'
2522
2536
 
2537
+ Naming/InclusiveLanguage:
2538
+ Description: 'Recommend the use of inclusive language instead of problematic terms.'
2539
+ Enabled: pending
2540
+ VersionAdded: '1.18'
2541
+ CheckIdentifiers: true
2542
+ CheckConstants: true
2543
+ CheckVariables: true
2544
+ CheckStrings: false
2545
+ CheckSymbols: true
2546
+ CheckComments: true
2547
+ CheckFilepaths: true
2548
+ FlaggedTerms:
2549
+ whitelist:
2550
+ Regex: !ruby/regexp '/white[-_\s]?list/'
2551
+ Suggestions:
2552
+ - allowlist
2553
+ - permit
2554
+ blacklist:
2555
+ Regex: !ruby/regexp '/black[-_\s]?list/'
2556
+ Suggestions:
2557
+ - denylist
2558
+ - block
2559
+ slave:
2560
+ Suggestions: ['replica', 'secondary', 'follower']
2561
+
2523
2562
  Naming/MemoizedInstanceVariableName:
2524
2563
  Description: >-
2525
2564
  Memoized method name should match memo instance variable name.
@@ -3111,6 +3150,7 @@ Style/CommentAnnotation:
3111
3150
  - HACK
3112
3151
  - REVIEW
3113
3152
  - NOTE
3153
+ RequireColon: true
3114
3154
 
3115
3155
  Style/CommentedKeyword:
3116
3156
  Description: 'Do not place comments on the same line as certain keywords.'
@@ -4576,7 +4616,8 @@ Style/StringConcatenation:
4576
4616
  Enabled: true
4577
4617
  Safe: false
4578
4618
  VersionAdded: '0.89'
4579
- VersionChanged: '1.6'
4619
+ VersionChanged: '1.18'
4620
+ Mode: aggressive
4580
4621
 
4581
4622
  Style/StringHashKeys:
4582
4623
  Description: 'Prefer symbols instead of strings as hash keys.'
data/lib/rubocop.rb CHANGED
@@ -211,6 +211,7 @@ require_relative 'rubocop/cop/layout/indentation_width'
211
211
  require_relative 'rubocop/cop/layout/initial_indentation'
212
212
  require_relative 'rubocop/cop/layout/leading_comment_space'
213
213
  require_relative 'rubocop/cop/layout/leading_empty_lines'
214
+ require_relative 'rubocop/cop/layout/line_end_string_concatenation_indentation'
214
215
  require_relative 'rubocop/cop/layout/line_length'
215
216
  require_relative 'rubocop/cop/layout/multiline_array_brace_layout'
216
217
  require_relative 'rubocop/cop/layout/multiline_array_line_breaks'
@@ -400,6 +401,7 @@ require_relative 'rubocop/cop/naming/constant_name'
400
401
  require_relative 'rubocop/cop/naming/file_name'
401
402
  require_relative 'rubocop/cop/naming/heredoc_delimiter_case'
402
403
  require_relative 'rubocop/cop/naming/heredoc_delimiter_naming'
404
+ require_relative 'rubocop/cop/naming/inclusive_language'
403
405
  require_relative 'rubocop/cop/naming/memoized_instance_variable_name'
404
406
  require_relative 'rubocop/cop/naming/method_name'
405
407
  require_relative 'rubocop/cop/naming/method_parameter_name'
@@ -19,7 +19,7 @@ module RuboCop
19
19
 
20
20
  puts
21
21
  puts 'Tip: Based on detected gems, the following '\
22
- 'RuboCop extension libraries might be helpful:'
22
+ 'RuboCop extension libraries might be helpful:'
23
23
 
24
24
  extensions.sort.each do |extension|
25
25
  puts " * #{extension} (https://github.com/rubocop/#{extension})"
@@ -27,8 +27,8 @@ module RuboCop
27
27
 
28
28
  puts
29
29
  puts 'You can opt out of this message by adding the following to your config '\
30
- '(see https://docs.rubocop.org/rubocop/extensions.html#extension-suggestions '\
31
- 'for more options):'
30
+ '(see https://docs.rubocop.org/rubocop/extensions.html#extension-suggestions '\
31
+ 'for more options):'
32
32
  puts ' AllCops:'
33
33
  puts ' SuggestExtensions: false'
34
34
 
@@ -229,7 +229,7 @@ module RuboCop
229
229
  line1 = key1.start_line + 1
230
230
  line2 = key2.start_line + 1
231
231
  "#{smart_path}:#{line1}: " \
232
- "`#{value}` is concealed by line #{line2}"
232
+ "`#{value}` is concealed by line #{line2}"
233
233
  else
234
234
  "#{smart_path}: `#{value}` is concealed by duplicate"
235
235
  end
@@ -23,7 +23,7 @@ module RuboCop
23
23
  def resolve_inheritance(path, hash, file, debug) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
24
24
  inherited_files = Array(hash['inherit_from'])
25
25
  base_configs(path, inherited_files, file)
26
- .reverse.each_with_index do |base_config, index|
26
+ .each_with_index.reverse_each do |base_config, index|
27
27
  override_department_setting_for_cops(base_config, hash)
28
28
  override_enabled_for_disabled_departments(base_config, hash)
29
29
 
@@ -81,11 +81,11 @@ module RuboCop
81
81
 
82
82
  msg = if last_version
83
83
  "RuboCop found unsupported Ruby version #{target_ruby_version} " \
84
- "in #{source}. #{target_ruby_version}-compatible " \
85
- "analysis was dropped after version #{last_version}."
84
+ "in #{source}. #{target_ruby_version}-compatible " \
85
+ "analysis was dropped after version #{last_version}."
86
86
  else
87
87
  'RuboCop found unknown Ruby version ' \
88
- "#{target_ruby_version.inspect} in #{source}."
88
+ "#{target_ruby_version.inspect} in #{source}."
89
89
  end
90
90
 
91
91
  msg += "\nSupported versions: #{TargetRuby.supported_versions.join(', ')}"
@@ -104,12 +104,9 @@ module RuboCop
104
104
  # to do so than to pass the value around to various methods.
105
105
  next if name == 'inherit_mode'
106
106
 
107
- suggestions = NameSimilarity.find_similar_names(name, Cop::Registry.global.map(&:cop_name))
108
- suggestion = "Did you mean `#{suggestions.join('`, `')}`?" if suggestions.any?
109
-
110
107
  message = <<~MESSAGE.rstrip
111
- unrecognized cop #{name} found in #{smart_loaded_path}
112
- #{suggestion}
108
+ unrecognized cop or department #{name} found in #{smart_loaded_path}
109
+ #{suggestion(name)}
113
110
  MESSAGE
114
111
 
115
112
  unknown_cops << message
@@ -117,6 +114,22 @@ module RuboCop
117
114
  raise ValidationError, unknown_cops.join("\n") if unknown_cops.any?
118
115
  end
119
116
 
117
+ def suggestion(name)
118
+ registry = Cop::Registry.global
119
+ departments = registry.departments.map(&:to_s)
120
+ suggestions = NameSimilarity.find_similar_names(name, departments + registry.map(&:cop_name))
121
+ if suggestions.any?
122
+ "Did you mean `#{suggestions.join('`, `')}`?"
123
+ else
124
+ # Department names can contain slashes, e.g. Chef/Correctness, but there's no support for
125
+ # the concept of higher level departments in RuboCop. It's a flat structure. So if the user
126
+ # tries to configure a "top level department", we hint that it's the bottom level
127
+ # departments that should be configured.
128
+ suggestions = departments.select { |department| department.start_with?("#{name}/") }
129
+ "#{name} is not a department. Use `#{suggestions.join('`, `')}`." if suggestions.any?
130
+ end
131
+ end
132
+
120
133
  def validate_syntax_cop
121
134
  syntax_config = @config['Lint/Syntax']
122
135
  default_config = ConfigLoader.default_configuration['Lint/Syntax']
@@ -179,8 +192,8 @@ module RuboCop
179
192
  next if validate_support_and_has_list(name, style, valid)
180
193
 
181
194
  msg = "invalid #{style_name} '#{style}' for #{name} found in " \
182
- "#{smart_loaded_path}\n" \
183
- "Valid choices are: #{valid.join(', ')}"
195
+ "#{smart_loaded_path}\n" \
196
+ "Valid choices are: #{valid.join(', ')}"
184
197
  raise ValidationError, msg
185
198
  end
186
199
  end
@@ -261,7 +261,7 @@ module RuboCop
261
261
  # @deprecated Make potential errors with previous API more obvious
262
262
  def offenses
263
263
  raise 'The offenses are not directly available; ' \
264
- 'they are returned as the result of the investigation'
264
+ 'they are returned as the result of the investigation'
265
265
  end
266
266
 
267
267
  ### Reserved for Commissioner
@@ -441,7 +441,7 @@ module RuboCop
441
441
  severity.to_sym
442
442
  else
443
443
  message = "Warning: Invalid severity '#{severity}'. " \
444
- "Valid severities are #{Severity::NAMES.join(', ')}."
444
+ "Valid severities are #{Severity::NAMES.join(', ')}."
445
445
  warn(Rainbow(message).red)
446
446
  end
447
447
  end
@@ -39,7 +39,7 @@ module RuboCop
39
39
  include RangeHelp
40
40
 
41
41
  MSG = 'Gem `%<gem_name>s` requirements already given on line '\
42
- '%<line_of_first_occurrence>d of the Gemfile.'
42
+ '%<line_of_first_occurrence>d of the Gemfile.'
43
43
 
44
44
  def on_new_investigation
45
45
  return if processed_source.blank?
@@ -3,8 +3,8 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Bundler
6
- # Enforce that Gem version specifications are either required
7
- # or forbidden.
6
+ # Enforce that Gem version specifications or a commit reference (branch,
7
+ # ref, or tag) are either required or forbidden.
8
8
  #
9
9
  # @example EnforcedStyle: required (default)
10
10
  # # bad
@@ -19,6 +19,15 @@ module RuboCop
19
19
  # # good
20
20
  # gem 'rubocop', '>= 1.5.0', '< 1.10.0'
21
21
  #
22
+ # # good
23
+ # gem 'rubocop', branch: 'feature-branch'
24
+ #
25
+ # # good
26
+ # gem 'rubocop', ref: '74b5bfbb2c4b6fd6cdbbc7254bd7084b36e0c85b'
27
+ #
28
+ # # good
29
+ # gem 'rubocop', tag: 'v1.17.0'
30
+ #
22
31
  # @example EnforcedStyle: forbidden
23
32
  # # good
24
33
  # gem 'rubocop'
@@ -32,6 +41,15 @@ module RuboCop
32
41
  # # bad
33
42
  # gem 'rubocop', '>= 1.5.0', '< 1.10.0'
34
43
  #
44
+ # # bad
45
+ # gem 'rubocop', branch: 'feature-branch'
46
+ #
47
+ # # bad
48
+ # gem 'rubocop', ref: '74b5bfbb2c4b6fd6cdbbc7254bd7084b36e0c85b'
49
+ #
50
+ # # bad
51
+ # gem 'rubocop', tag: 'v1.17.0'
52
+ #
35
53
  class GemVersion < Base
36
54
  include ConfigurableEnforcedStyle
37
55
  include GemDeclaration
@@ -45,6 +63,11 @@ module RuboCop
45
63
  (send nil? :gem <(str #version_specification?) ...>)
46
64
  PATTERN
47
65
 
66
+ # @!method includes_commit_reference?(node)
67
+ def_node_matcher :includes_commit_reference?, <<~PATTERN
68
+ (send nil? :gem <(hash <(pair (sym {:branch :ref :tag}) (str _)) ...>) ...>)
69
+ PATTERN
70
+
48
71
  def on_send(node)
49
72
  return unless gem_declaration?(node)
50
73
  return if allowed_gem?(node)
@@ -78,8 +101,19 @@ module RuboCop
78
101
  end
79
102
 
80
103
  def offense?(node)
81
- (required_style? && !includes_version_specification?(node)) ||
82
- (forbidden_style? && includes_version_specification?(node))
104
+ required_offense?(node) || forbidden_offense?(node)
105
+ end
106
+
107
+ def required_offense?(node)
108
+ return unless required_style?
109
+
110
+ !includes_version_specification?(node) && !includes_commit_reference?(node)
111
+ end
112
+
113
+ def forbidden_offense?(node)
114
+ return unless forbidden_style?
115
+
116
+ includes_version_specification?(node) || includes_commit_reference?(node)
83
117
  end
84
118
 
85
119
  def forbidden_style?