rubocop 1.17.0 → 1.18.4

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 (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?