rubocop 0.78.0 → 0.79.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 (35) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +2 -1
  4. data/lib/rubocop.rb +6 -0
  5. data/lib/rubocop/ast/builder.rb +43 -42
  6. data/lib/rubocop/ast/node/def_node.rb +11 -0
  7. data/lib/rubocop/ast/node/forward_args_node.rb +18 -0
  8. data/lib/rubocop/ast/traversal.rb +11 -3
  9. data/lib/rubocop/cli/command/show_cops.rb +11 -4
  10. data/lib/rubocop/config_loader.rb +19 -19
  11. data/lib/rubocop/config_validator.rb +49 -91
  12. data/lib/rubocop/cop/autocorrect_logic.rb +6 -3
  13. data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +1 -1
  14. data/lib/rubocop/cop/generator.rb +3 -4
  15. data/lib/rubocop/cop/generator/configuration_injector.rb +1 -1
  16. data/lib/rubocop/cop/layout/hash_alignment.rb +8 -4
  17. data/lib/rubocop/cop/layout/multiline_block_layout.rb +14 -5
  18. data/lib/rubocop/cop/layout/space_before_block_braces.rb +2 -2
  19. data/lib/rubocop/cop/lint/debugger.rb +2 -2
  20. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +1 -1
  21. data/lib/rubocop/cop/migration/department_name.rb +16 -1
  22. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +1 -7
  23. data/lib/rubocop/cop/naming/method_parameter_name.rb +1 -1
  24. data/lib/rubocop/cop/registry.rb +7 -2
  25. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +4 -207
  26. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +168 -0
  27. data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +54 -0
  28. data/lib/rubocop/cop/style/multiline_when_then.rb +5 -1
  29. data/lib/rubocop/cop/style/numeric_predicate.rb +4 -3
  30. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +7 -7
  31. data/lib/rubocop/cop/style/yoda_condition.rb +16 -1
  32. data/lib/rubocop/rspec/shared_contexts.rb +5 -0
  33. data/lib/rubocop/target_ruby.rb +151 -0
  34. data/lib/rubocop/version.rb +1 -1
  35. metadata +8 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a1c6769965ef19c24fed5115e5ee0e6949aef81f2d4f0c64a28e867b694b8f8b
4
- data.tar.gz: 6785ee7c23edbb4b47414ca32a9cb7b7e24565c454c8e4a33f742b9a15de8e5b
3
+ metadata.gz: 3bdc80758a1e3604ccf4fc91cedac86412bea6d234b27c9b7ae064fb364076ce
4
+ data.tar.gz: 2890ef6acaede12b528cf963cdbb8a90f64ecbcef6c5da6b3684fcf90c7d4c07
5
5
  SHA512:
6
- metadata.gz: e3e28e9ed24f5e757ce4c24f4ee4d079eb5e7ac1c6f50bd50fb512c5b4986d84ec19b0ba426a9b077ca734177a5e5139a50c12f5fe331216abee67bd6a2436b4
7
- data.tar.gz: 2f2739072557a141d69a51037e38a0973bee53caf40d216610eaffd3a8f14409e64562ed71a49803ad8b11b71fedc51312657efaecb27189900c7b5c44b2cb8c
6
+ metadata.gz: 8eb332a372b879708bedba857c21532665ad9b459b18977180fdc5d5ec0cb0f035968a907adfe70bd6e5688a97d9c321503d97d37e87cbf77b04168d1e071c1d
7
+ data.tar.gz: 98d0a07c70c4dca7c63cc96fb473a0079eee449d045b3543b55b90da3f1700c564d0f2ab7ccd909f63fefff7956680fd862710fabe2ccb0e9969b424b943216d
data/README.md CHANGED
@@ -53,7 +53,7 @@ haven't reached version 1.0 yet). To prevent an unwanted RuboCop update you
53
53
  might want to use a conservative version lock in your `Gemfile`:
54
54
 
55
55
  ```rb
56
- gem 'rubocop', '~> 0.78.0', require: false
56
+ gem 'rubocop', '~> 0.79.0', require: false
57
57
  ```
58
58
 
59
59
  ## Quickstart
@@ -2758,7 +2758,7 @@ Style/FrozenStringLiteralComment:
2758
2758
  to help transition to frozen string literals by default.
2759
2759
  Enabled: true
2760
2760
  VersionAdded: '0.36'
2761
- VersionChanged: '0.69'
2761
+ VersionChanged: '0.79'
2762
2762
  EnforcedStyle: always
2763
2763
  SupportedStyles:
2764
2764
  # `always` will always add the frozen string literal comment to a file
@@ -2769,6 +2769,7 @@ Style/FrozenStringLiteralComment:
2769
2769
  # `never` will enforce that the frozen string literal comment does not
2770
2770
  # exist in a file.
2771
2771
  - never
2772
+ Safe: false
2772
2773
 
2773
2774
  Style/GlobalVars:
2774
2775
  Description: 'Do not introduce global variables.'
@@ -43,6 +43,7 @@ require_relative 'rubocop/ast/node/def_node'
43
43
  require_relative 'rubocop/ast/node/defined_node'
44
44
  require_relative 'rubocop/ast/node/ensure_node'
45
45
  require_relative 'rubocop/ast/node/for_node'
46
+ require_relative 'rubocop/ast/node/forward_args_node'
46
47
  require_relative 'rubocop/ast/node/float_node'
47
48
  require_relative 'rubocop/ast/node/hash_node'
48
49
  require_relative 'rubocop/ast/node/if_node'
@@ -459,7 +460,11 @@ require_relative 'rubocop/cop/style/lambda'
459
460
  require_relative 'rubocop/cop/style/lambda_call'
460
461
  require_relative 'rubocop/cop/style/line_end_concatenation'
461
462
  require_relative 'rubocop/cop/style/method_call_without_args_parentheses'
463
+ # rubocop:disable Layout/LineLength
462
464
  require_relative 'rubocop/cop/style/method_call_with_args_parentheses'
465
+ require_relative 'rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses'
466
+ require_relative 'rubocop/cop/style/method_call_with_args_parentheses/require_parentheses'
467
+ # rubocop:enable Layout/LineLength
463
468
  require_relative 'rubocop/cop/style/method_called_on_do_end_block'
464
469
  require_relative 'rubocop/cop/style/method_def_parentheses'
465
470
  require_relative 'rubocop/cop/style/method_missing_super'
@@ -616,4 +621,5 @@ require_relative 'rubocop/cli/command/show_cops'
616
621
  require_relative 'rubocop/cli/command/version'
617
622
  require_relative 'rubocop/options'
618
623
  require_relative 'rubocop/remote_config'
624
+ require_relative 'rubocop/target_ruby'
619
625
  require_relative 'rubocop/yaml_duplication_checker'
@@ -15,48 +15,49 @@ module RuboCop
15
15
  # root_node = parser.parse(buffer)
16
16
  class Builder < Parser::Builders::Default
17
17
  NODE_MAP = {
18
- and: AndNode,
19
- alias: AliasNode,
20
- args: ArgsNode,
21
- array: ArrayNode,
22
- block: BlockNode,
23
- break: BreakNode,
24
- case: CaseNode,
25
- class: ClassNode,
26
- def: DefNode,
27
- defined?: DefinedNode,
28
- defs: DefNode,
29
- ensure: EnsureNode,
30
- for: ForNode,
31
- float: FloatNode,
32
- hash: HashNode,
33
- if: IfNode,
34
- int: IntNode,
35
- irange: RangeNode,
36
- erange: RangeNode,
37
- kwsplat: KeywordSplatNode,
38
- module: ModuleNode,
39
- or: OrNode,
40
- pair: PairNode,
41
- regexp: RegexpNode,
42
- resbody: ResbodyNode,
43
- retry: RetryNode,
44
- return: ReturnNode,
45
- csend: SendNode,
46
- send: SendNode,
47
- str: StrNode,
48
- dstr: StrNode,
49
- xstr: StrNode,
50
- sclass: SelfClassNode,
51
- super: SuperNode,
52
- zsuper: SuperNode,
53
- sym: SymbolNode,
54
- until: UntilNode,
55
- until_post: UntilNode,
56
- when: WhenNode,
57
- while: WhileNode,
58
- while_post: WhileNode,
59
- yield: YieldNode
18
+ and: AndNode,
19
+ alias: AliasNode,
20
+ args: ArgsNode,
21
+ array: ArrayNode,
22
+ block: BlockNode,
23
+ break: BreakNode,
24
+ case: CaseNode,
25
+ class: ClassNode,
26
+ def: DefNode,
27
+ defined?: DefinedNode,
28
+ defs: DefNode,
29
+ ensure: EnsureNode,
30
+ for: ForNode,
31
+ forward_args: ForwardArgsNode,
32
+ float: FloatNode,
33
+ hash: HashNode,
34
+ if: IfNode,
35
+ int: IntNode,
36
+ irange: RangeNode,
37
+ erange: RangeNode,
38
+ kwsplat: KeywordSplatNode,
39
+ module: ModuleNode,
40
+ or: OrNode,
41
+ pair: PairNode,
42
+ regexp: RegexpNode,
43
+ resbody: ResbodyNode,
44
+ retry: RetryNode,
45
+ return: ReturnNode,
46
+ csend: SendNode,
47
+ send: SendNode,
48
+ str: StrNode,
49
+ dstr: StrNode,
50
+ xstr: StrNode,
51
+ sclass: SelfClassNode,
52
+ super: SuperNode,
53
+ zsuper: SuperNode,
54
+ sym: SymbolNode,
55
+ until: UntilNode,
56
+ until_post: UntilNode,
57
+ when: WhenNode,
58
+ while: WhileNode,
59
+ while_post: WhileNode,
60
+ yield: YieldNode
60
61
  }.freeze
61
62
 
62
63
  # Generates {Node} from the given information.
@@ -16,6 +16,17 @@ module RuboCop
16
16
  method?(:initialize) || assignment_method?
17
17
  end
18
18
 
19
+ # Checks whether this method definition node forwards its arguments
20
+ # as per the feature added in Ruby 2.7.
21
+ #
22
+ # @note This is written in a way that may support lead arguments
23
+ # which are rumored to be added in a later version of Ruby.
24
+ #
25
+ # @return [Boolean] whether the `def` node uses argument forwarding
26
+ def argument_forwarding?
27
+ arguments.any?(&:forward_args_type?)
28
+ end
29
+
19
30
  # The name of the defined method as a symbol.
20
31
  #
21
32
  # @return [Symbol] the name of the defined method
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module AST
5
+ # A node extension for `forward-args` nodes. This will be used in place
6
+ # of a plain node when the builder constructs the AST, making its methods
7
+ # available to all `forward-args` nodes within RuboCop.
8
+ class ForwardArgsNode < Node
9
+ include CollectionNode
10
+
11
+ # Node wraps itself in an array to be compatible with other
12
+ # enumerable argument types.
13
+ def to_a
14
+ [self]
15
+ end
16
+ end
17
+ end
18
+ end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # rubocop:disable Metrics/ModuleLength
3
4
  module RuboCop
4
5
  module AST
5
6
  # Provides methods for traversing an AST.
@@ -18,15 +19,21 @@ module RuboCop
18
19
  rational str sym regopt self lvar
19
20
  ivar cvar gvar nth_ref back_ref cbase
20
21
  arg restarg blockarg shadowarg
21
- kwrestarg zsuper lambda redo retry].freeze
22
+ kwrestarg zsuper lambda redo retry
23
+ forward_args forwarded_args
24
+ match_var match_nil_pattern].freeze
22
25
  ONE_CHILD_NODE = %i[splat kwsplat block_pass not break next
23
26
  preexe postexe match_current_line defined?
24
- arg_expr].freeze
27
+ arg_expr pin match_rest if_guard unless_guard
28
+ match_with_trailing_comma].freeze
25
29
  MANY_CHILD_NODES = %i[dstr dsym xstr regexp array hash pair
26
30
  mlhs masgn or_asgn and_asgn
27
31
  undef alias args super yield or and
28
32
  while_post until_post iflipflop eflipflop
29
- match_with_lvasgn begin kwbegin return].freeze
33
+ match_with_lvasgn begin kwbegin return
34
+ in_match case_match in_pattern match_alt
35
+ match_as array_pattern array_pattern_with_tail
36
+ hash_pattern const_pattern].freeze
30
37
  SECOND_CHILD_ONLY = %i[lvasgn ivasgn cvasgn gvasgn optarg kwarg
31
38
  kwoptarg].freeze
32
39
 
@@ -181,3 +188,4 @@ module RuboCop
181
188
  end
182
189
  end
183
190
  end
191
+ # rubocop:enable Metrics/ModuleLength
@@ -8,6 +8,13 @@ module RuboCop
8
8
  class ShowCops < Base
9
9
  self.command_name = :show_cops
10
10
 
11
+ def initialize(env)
12
+ super
13
+
14
+ # Load the configs so the require()s are done for custom cops
15
+ @config = @config_store.for(Dir.pwd)
16
+ end
17
+
11
18
  def run
12
19
  print_available_cops
13
20
  end
@@ -15,8 +22,6 @@ module RuboCop
15
22
  private
16
23
 
17
24
  def print_available_cops
18
- # Load the configs so the require()s are done for custom cops
19
- @config_store.for(Dir.pwd)
20
25
  registry = Cop::Cop.registry
21
26
  show_all = @options[:show_cops].empty?
22
27
 
@@ -46,7 +51,9 @@ module RuboCop
46
51
 
47
52
  def print_cop_details(cops)
48
53
  cops.each do |cop|
49
- puts '# Supports --auto-correct' if cop.new.support_autocorrect?
54
+ if cop.new(@config).support_autocorrect?
55
+ puts '# Supports --auto-correct'
56
+ end
50
57
  puts "#{cop.cop_name}:"
51
58
  puts config_lines(cop)
52
59
  puts
@@ -64,7 +71,7 @@ module RuboCop
64
71
  end
65
72
 
66
73
  def config_lines(cop)
67
- cnf = @config_store.for(Dir.pwd).for_cop(cop)
74
+ cnf = @config.for_cop(cop)
68
75
  cnf.to_yaml.lines.to_a.drop(1).map { |line| ' ' + line }
69
76
  end
70
77
  end
@@ -91,7 +91,9 @@ module RuboCop
91
91
  else
92
92
  add_excludes_from_files(config, config_file)
93
93
  end
94
- merge_with_default(config, config_file)
94
+ merge_with_default(config, config_file).tap do |merged_config|
95
+ warn_on_pending_cops(merged_config)
96
+ end
95
97
  end
96
98
 
97
99
  def add_excludes_from_files(config, config_file)
@@ -114,6 +116,22 @@ module RuboCop
114
116
  end
115
117
  end
116
118
 
119
+ def warn_on_pending_cops(config)
120
+ pending_cops = config.keys.select do |key|
121
+ config[key]['Enabled'] == 'pending'
122
+ end
123
+
124
+ return if pending_cops.none?
125
+
126
+ warn Rainbow('The following cops were added to RuboCop, but are not ' \
127
+ 'configured. Please set Enabled to either `true` or ' \
128
+ '`false` in your `.rubocop.yml` file:').yellow
129
+
130
+ pending_cops.each do |cop|
131
+ warn Rainbow(" - #{cop}").yellow
132
+ end
133
+ end
134
+
117
135
  # Merges the given configuration with the default one. If
118
136
  # AllCops:DisabledByDefault is true, it changes the Enabled params so
119
137
  # that only cops from user configuration are enabled.
@@ -199,8 +217,6 @@ module RuboCop
199
217
  raise(TypeError, "Malformed configuration in #{absolute_path}")
200
218
  end
201
219
 
202
- check_cop_config_value(hash)
203
-
204
220
  hash
205
221
  end
206
222
 
@@ -222,22 +238,6 @@ module RuboCop
222
238
  end
223
239
  end
224
240
 
225
- def check_cop_config_value(hash, parent = nil)
226
- hash.each do |key, value|
227
- check_cop_config_value(value, key) if value.is_a?(Hash)
228
-
229
- next unless %w[Enabled
230
- Safe
231
- SafeAutoCorrect
232
- AutoCorrect].include?(key) && value.is_a?(String)
233
-
234
- abort(
235
- "Property #{Rainbow(key).yellow} of cop #{Rainbow(parent).yellow}" \
236
- " is supposed to be a boolean and #{Rainbow(value).yellow} is not."
237
- )
238
- end
239
- end
240
-
241
241
  # Read the specified file, or exit with a friendly, concise message on
242
242
  # stderr. Care is taken to use the standard OS exit code for a "file not
243
243
  # found" error.
@@ -14,25 +14,19 @@ module RuboCop
14
14
  VersionAdded VersionChanged VersionRemoved
15
15
  Reference Safe SafeAutoCorrect].freeze
16
16
 
17
- # 2.3 is the oldest officially supported Ruby version.
18
- DEFAULT_RUBY_VERSION = 2.3
19
- KNOWN_RUBIES = [2.3, 2.4, 2.5, 2.6, 2.7].freeze
20
- OBSOLETE_RUBIES = {
21
- 1.9 => '0.50', 2.0 => '0.50', 2.1 => '0.58', 2.2 => '0.69'
22
- }.freeze
23
- RUBY_VERSION_FILENAME = '.ruby-version'
24
-
25
- def_delegators :@config,
26
- :smart_loaded_path, :for_all_cops, :find_file_upwards,
27
- :base_dir_for_path_parameters, :bundler_lock_file_path
17
+ def_delegators :@config, :smart_loaded_path, :for_all_cops
28
18
 
29
19
  def initialize(config)
30
20
  @config = config
31
21
  @config_obsoletion = ConfigObsoletion.new(config)
22
+ @target_ruby = TargetRuby.new(config)
32
23
  end
33
24
 
34
25
  def validate
35
- # Don't validate RuboCop's own files. Avoids infinite recursion.
26
+ check_cop_config_value(@config)
27
+ reject_conflicting_safe_settings
28
+
29
+ # Don't validate RuboCop's own files further. Avoids infinite recursion.
36
30
  return if @config.internal?
37
31
 
38
32
  valid_cop_names, invalid_cop_names = @config.keys.partition do |key|
@@ -50,23 +44,7 @@ module RuboCop
50
44
  end
51
45
 
52
46
  def target_ruby_version
53
- @target_ruby_version ||= begin
54
- if for_all_cops['TargetRubyVersion']
55
- @target_ruby_version_source = :rubocop_yml
56
-
57
- for_all_cops['TargetRubyVersion'].to_f
58
- elsif target_ruby_version_from_version_file
59
- @target_ruby_version_source = :ruby_version_file
60
-
61
- target_ruby_version_from_version_file
62
- elsif target_ruby_version_from_bundler_lock_file
63
- @target_ruby_version_source = :bundler_lock_file
64
-
65
- target_ruby_version_from_bundler_lock_file
66
- else
67
- DEFAULT_RUBY_VERSION
68
- end
69
- end
47
+ target_ruby.version
70
48
  end
71
49
 
72
50
  def validate_section_presence(name)
@@ -78,20 +56,24 @@ module RuboCop
78
56
 
79
57
  private
80
58
 
59
+ attr_reader :target_ruby
60
+
81
61
  def check_target_ruby
82
- return if KNOWN_RUBIES.include?(target_ruby_version)
62
+ return if target_ruby.supported?
83
63
 
84
- msg = if OBSOLETE_RUBIES.include?(target_ruby_version)
64
+ source = target_ruby.source
65
+ last_version = target_ruby.rubocop_version_with_support
66
+
67
+ msg = if last_version
85
68
  "RuboCop found unsupported Ruby version #{target_ruby_version} " \
86
- "in #{target_ruby_source}. #{target_ruby_version}-compatible " \
87
- 'analysis was dropped after version ' \
88
- "#{OBSOLETE_RUBIES[target_ruby_version]}."
69
+ "in #{source}. #{target_ruby_version}-compatible " \
70
+ "analysis was dropped after version #{last_version}."
89
71
  else
90
72
  'RuboCop found unknown Ruby version ' \
91
- "#{target_ruby_version.inspect} in #{target_ruby_source}."
73
+ "#{target_ruby_version.inspect} in #{source}."
92
74
  end
93
75
 
94
- msg += "\nSupported versions: #{KNOWN_RUBIES.join(', ')}"
76
+ msg += "\nSupported versions: #{TargetRuby.supported_versions.join(', ')}"
95
77
 
96
78
  raise ValidationError, msg
97
79
  end
@@ -178,71 +160,47 @@ module RuboCop
178
160
  formats.all? { |format| valid.include?(format) }
179
161
  end
180
162
 
181
- def target_ruby_source
182
- case @target_ruby_version_source
183
- when :ruby_version_file
184
- "`#{RUBY_VERSION_FILENAME}`"
185
- when :bundler_lock_file
186
- "`#{bundler_lock_file_path}`"
187
- when :rubocop_yml
188
- "`TargetRubyVersion` parameter (in #{smart_loaded_path})"
189
- end
190
- end
163
+ def reject_mutually_exclusive_defaults
164
+ disabled_by_default = for_all_cops['DisabledByDefault']
165
+ enabled_by_default = for_all_cops['EnabledByDefault']
166
+ return unless disabled_by_default && enabled_by_default
191
167
 
192
- def ruby_version_file
193
- @ruby_version_file ||=
194
- find_file_upwards(RUBY_VERSION_FILENAME, base_dir_for_path_parameters)
168
+ msg = 'Cops cannot be both enabled by default and disabled by default'
169
+ raise ValidationError, msg
195
170
  end
196
171
 
197
- def target_ruby_version_from_version_file
198
- file = ruby_version_file
199
- return unless file && File.file?(file)
172
+ def reject_conflicting_safe_settings
173
+ @config.each do |name, cop_config|
174
+ next unless cop_config.is_a?(Hash)
175
+ next unless cop_config['Safe'] == false &&
176
+ cop_config['SafeAutoCorrect'] == true
200
177
 
201
- @target_ruby_version_from_version_file ||=
202
- File.read(file).match(/\A(ruby-)?(?<version>\d+\.\d+)/) do |md|
203
- md[:version].to_f
204
- end
178
+ msg = 'Unsafe cops cannot have a safe auto-correction ' \
179
+ "(section #{name} in #{smart_loaded_path})"
180
+ raise ValidationError, msg
181
+ end
205
182
  end
206
183
 
207
- def target_ruby_version_from_bundler_lock_file
208
- @target_ruby_version_from_bundler_lock_file ||=
209
- read_ruby_version_from_bundler_lock_file
210
- end
184
+ def check_cop_config_value(hash, parent = nil)
185
+ hash.each do |key, value|
186
+ check_cop_config_value(value, key) if value.is_a?(Hash)
187
+
188
+ next unless %w[Enabled
189
+ Safe
190
+ SafeAutoCorrect
191
+ AutoCorrect].include?(key) && value.is_a?(String)
192
+
193
+ next if key == 'Enabled' && value == 'pending'
211
194
 
212
- def read_ruby_version_from_bundler_lock_file
213
- lock_file_path = bundler_lock_file_path
214
- return nil unless lock_file_path
215
-
216
- in_ruby_section = false
217
- File.foreach(lock_file_path) do |line|
218
- # If ruby is in Gemfile.lock or gems.lock, there should be two lines
219
- # towards the bottom of the file that look like:
220
- # RUBY VERSION
221
- # ruby W.X.YpZ
222
- # We ultimately want to match the "ruby W.X.Y.pZ" line, but there's
223
- # extra logic to make sure we only start looking once we've seen the
224
- # "RUBY VERSION" line.
225
- in_ruby_section ||= line.match(/^\s*RUBY\s*VERSION\s*$/)
226
- next unless in_ruby_section
227
-
228
- # We currently only allow this feature to work with MRI ruby. If jruby
229
- # (or something else) is used by the project, it's lock file will have a
230
- # line that looks like:
231
- # RUBY VERSION
232
- # ruby W.X.YpZ (jruby x.x.x.x)
233
- # The regex won't match in this situation.
234
- result = line.match(/^\s*ruby\s+(\d+\.\d+)[p.\d]*\s*$/)
235
- return result.captures.first.to_f if result
195
+ raise ValidationError, msg_not_boolean(parent, key, value)
236
196
  end
237
197
  end
238
198
 
239
- def reject_mutually_exclusive_defaults
240
- disabled_by_default = for_all_cops['DisabledByDefault']
241
- enabled_by_default = for_all_cops['EnabledByDefault']
242
- return unless disabled_by_default && enabled_by_default
243
-
244
- msg = 'Cops cannot be both enabled by default and disabled by default'
245
- raise ValidationError, msg
199
+ # FIXME: Handling colors in exception messages like this is ugly.
200
+ def msg_not_boolean(parent, key, value)
201
+ "#{Rainbow('').reset}" \
202
+ "Property #{Rainbow(key).yellow} of cop #{Rainbow(parent).yellow}" \
203
+ " is supposed to be a boolean and #{Rainbow(value).yellow} is not."
246
204
  end
247
205
  end
248
206
  end