rubocop 0.91.1 → 1.1.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 (116) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +8 -5
  3. data/config/default.yml +143 -56
  4. data/lib/rubocop.rb +17 -5
  5. data/lib/rubocop/cached_data.rb +2 -1
  6. data/lib/rubocop/cli/command/auto_genenerate_config.rb +1 -1
  7. data/lib/rubocop/cli/command/version.rb +1 -1
  8. data/lib/rubocop/comment_config.rb +1 -1
  9. data/lib/rubocop/config.rb +4 -0
  10. data/lib/rubocop/config_loader.rb +19 -2
  11. data/lib/rubocop/config_loader_resolver.rb +7 -5
  12. data/lib/rubocop/config_regeneration.rb +33 -0
  13. data/lib/rubocop/config_validator.rb +7 -6
  14. data/lib/rubocop/cop/badge.rb +9 -24
  15. data/lib/rubocop/cop/base.rb +16 -1
  16. data/lib/rubocop/cop/bundler/duplicated_gem.rb +23 -3
  17. data/lib/rubocop/cop/commissioner.rb +36 -22
  18. data/lib/rubocop/cop/corrector.rb +3 -1
  19. data/lib/rubocop/cop/correctors/line_break_corrector.rb +2 -2
  20. data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +1 -1
  21. data/lib/rubocop/cop/force.rb +1 -1
  22. data/lib/rubocop/cop/gemspec/required_ruby_version.rb +10 -10
  23. data/lib/rubocop/cop/layout/array_alignment.rb +1 -0
  24. data/lib/rubocop/cop/layout/class_structure.rb +7 -0
  25. data/lib/rubocop/cop/layout/def_end_alignment.rb +1 -1
  26. data/lib/rubocop/cop/layout/dot_position.rb +6 -9
  27. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +7 -7
  28. data/lib/rubocop/cop/layout/empty_lines_around_attribute_accessor.rb +1 -1
  29. data/lib/rubocop/cop/layout/extra_spacing.rb +1 -2
  30. data/lib/rubocop/cop/layout/space_around_equals_in_parameter_default.rb +2 -11
  31. data/lib/rubocop/cop/layout/space_around_operators.rb +4 -1
  32. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +0 -4
  33. data/lib/rubocop/cop/layout/trailing_whitespace.rb +37 -13
  34. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +2 -0
  35. data/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb +18 -1
  36. data/lib/rubocop/cop/lint/boolean_symbol.rb +3 -0
  37. data/lib/rubocop/cop/lint/debugger.rb +2 -3
  38. data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +77 -0
  39. data/lib/rubocop/cop/lint/empty_block.rb +46 -0
  40. data/lib/rubocop/cop/lint/flip_flop.rb +8 -2
  41. data/lib/rubocop/cop/lint/hash_compare_by_identity.rb +37 -0
  42. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +17 -3
  43. data/lib/rubocop/cop/lint/mixed_regexp_capture_types.rb +1 -0
  44. data/lib/rubocop/cop/lint/number_conversion.rb +46 -13
  45. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +27 -8
  46. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +1 -1
  47. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +78 -0
  48. data/lib/rubocop/cop/lint/to_enum_arguments.rb +95 -0
  49. data/lib/rubocop/cop/lint/to_json.rb +1 -1
  50. data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +185 -0
  51. data/lib/rubocop/cop/lint/useless_access_modifier.rb +2 -2
  52. data/lib/rubocop/cop/metrics/block_length.rb +3 -1
  53. data/lib/rubocop/cop/metrics/class_length.rb +14 -6
  54. data/lib/rubocop/cop/metrics/parameter_lists.rb +4 -1
  55. data/lib/rubocop/cop/mixin/hash_transform_method.rb +1 -1
  56. data/lib/rubocop/cop/mixin/line_length_help.rb +1 -1
  57. data/lib/rubocop/cop/naming/binary_operator_parameter_name.rb +1 -1
  58. data/lib/rubocop/cop/naming/predicate_name.rb +2 -1
  59. data/lib/rubocop/cop/offense.rb +18 -5
  60. data/lib/rubocop/cop/security/open.rb +12 -10
  61. data/lib/rubocop/cop/style/access_modifier_declarations.rb +6 -2
  62. data/lib/rubocop/cop/style/accessor_grouping.rb +3 -0
  63. data/lib/rubocop/cop/style/arguments_forwarding.rb +142 -0
  64. data/lib/rubocop/cop/style/array_coercion.rb +4 -0
  65. data/lib/rubocop/cop/style/case_like_if.rb +20 -4
  66. data/lib/rubocop/cop/style/class_equality_comparison.rb +64 -0
  67. data/lib/rubocop/cop/style/combinable_loops.rb +8 -1
  68. data/lib/rubocop/cop/style/comment_annotation.rb +6 -0
  69. data/lib/rubocop/cop/style/date_time.rb +12 -1
  70. data/lib/rubocop/cop/style/document_dynamic_eval_definition.rb +67 -0
  71. data/lib/rubocop/cop/style/explicit_block_argument.rb +6 -2
  72. data/lib/rubocop/cop/style/for.rb +0 -4
  73. data/lib/rubocop/cop/style/format_string_token.rb +48 -3
  74. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +10 -13
  75. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +6 -11
  76. data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +7 -11
  77. data/lib/rubocop/cop/style/method_def_parentheses.rb +0 -4
  78. data/lib/rubocop/cop/style/mixin_usage.rb +7 -27
  79. data/lib/rubocop/cop/style/multiple_comparison.rb +54 -7
  80. data/lib/rubocop/cop/style/nested_ternary_operator.rb +2 -0
  81. data/lib/rubocop/cop/style/optional_boolean_parameter.rb +11 -3
  82. data/lib/rubocop/cop/style/raise_args.rb +0 -3
  83. data/lib/rubocop/cop/style/redundant_begin.rb +36 -8
  84. data/lib/rubocop/cop/style/redundant_condition.rb +5 -1
  85. data/lib/rubocop/cop/style/redundant_interpolation.rb +6 -1
  86. data/lib/rubocop/cop/style/redundant_parentheses.rb +4 -0
  87. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +45 -24
  88. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +8 -15
  89. data/lib/rubocop/cop/style/redundant_self.rb +3 -0
  90. data/lib/rubocop/cop/style/safe_navigation.rb +16 -4
  91. data/lib/rubocop/cop/style/semicolon.rb +3 -0
  92. data/lib/rubocop/cop/style/string_concatenation.rb +14 -2
  93. data/lib/rubocop/cop/style/swap_values.rb +108 -0
  94. data/lib/rubocop/cop/style/ternary_parentheses.rb +1 -1
  95. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +3 -1
  96. data/lib/rubocop/cop/team.rb +6 -1
  97. data/lib/rubocop/cop/util.rb +1 -1
  98. data/lib/rubocop/cop/variable_force/branch.rb +0 -4
  99. data/lib/rubocop/ext/regexp_node.rb +29 -10
  100. data/lib/rubocop/ext/regexp_parser.rb +77 -0
  101. data/lib/rubocop/formatter/disabled_config_formatter.rb +12 -5
  102. data/lib/rubocop/formatter/formatter_set.rb +1 -1
  103. data/lib/rubocop/formatter/offense_count_formatter.rb +1 -1
  104. data/lib/rubocop/formatter/worst_offenders_formatter.rb +1 -1
  105. data/lib/rubocop/magic_comment.rb +2 -2
  106. data/lib/rubocop/options.rb +22 -17
  107. data/lib/rubocop/result_cache.rb +8 -2
  108. data/lib/rubocop/rspec/cop_helper.rb +1 -1
  109. data/lib/rubocop/rspec/expect_offense.rb +5 -5
  110. data/lib/rubocop/rspec/shared_contexts.rb +4 -0
  111. data/lib/rubocop/runner.rb +9 -5
  112. data/lib/rubocop/target_finder.rb +27 -26
  113. data/lib/rubocop/target_ruby.rb +1 -1
  114. data/lib/rubocop/version.rb +61 -6
  115. metadata +21 -16
  116. data/lib/rubocop/cop/mixin/regexp_literal_help.rb +0 -43
@@ -8,11 +8,14 @@ require 'set'
8
8
  require 'forwardable'
9
9
  require 'regexp_parser'
10
10
  require 'unicode/display_width/no_string_ext'
11
+
12
+ # we have to require RuboCop's version, before rubocop-ast's
13
+ require_relative 'rubocop/version'
11
14
  require 'rubocop-ast'
15
+
12
16
  require_relative 'rubocop/ast_aliases'
13
17
  require_relative 'rubocop/ext/regexp_node'
14
-
15
- require_relative 'rubocop/version'
18
+ require_relative 'rubocop/ext/regexp_parser'
16
19
 
17
20
  require_relative 'rubocop/core_ext/string'
18
21
  require_relative 'rubocop/ext/processed_source'
@@ -103,7 +106,6 @@ require_relative 'rubocop/cop/mixin/percent_literal'
103
106
  require_relative 'rubocop/cop/mixin/preceding_following_alignment'
104
107
  require_relative 'rubocop/cop/mixin/preferred_delimiters'
105
108
  require_relative 'rubocop/cop/mixin/rational_literal'
106
- require_relative 'rubocop/cop/mixin/regexp_literal_help'
107
109
  require_relative 'rubocop/cop/mixin/rescue_node'
108
110
  require_relative 'rubocop/cop/mixin/safe_assignment'
109
111
  require_relative 'rubocop/cop/mixin/space_after_punctuation'
@@ -261,10 +263,12 @@ require_relative 'rubocop/cop/lint/duplicate_case_condition'
261
263
  require_relative 'rubocop/cop/lint/duplicate_elsif_condition'
262
264
  require_relative 'rubocop/cop/lint/duplicate_hash_key'
263
265
  require_relative 'rubocop/cop/lint/duplicate_methods'
266
+ require_relative 'rubocop/cop/lint/duplicate_regexp_character_class_element'
264
267
  require_relative 'rubocop/cop/lint/duplicate_require'
265
268
  require_relative 'rubocop/cop/lint/duplicate_rescue_exception'
266
269
  require_relative 'rubocop/cop/lint/each_with_object_argument'
267
270
  require_relative 'rubocop/cop/lint/else_layout'
271
+ require_relative 'rubocop/cop/lint/empty_block'
268
272
  require_relative 'rubocop/cop/lint/empty_conditional_body'
269
273
  require_relative 'rubocop/cop/lint/empty_ensure'
270
274
  require_relative 'rubocop/cop/lint/empty_expression'
@@ -277,6 +281,7 @@ require_relative 'rubocop/cop/lint/flip_flop'
277
281
  require_relative 'rubocop/cop/lint/float_comparison'
278
282
  require_relative 'rubocop/cop/lint/float_out_of_range'
279
283
  require_relative 'rubocop/cop/lint/format_parameter_mismatch'
284
+ require_relative 'rubocop/cop/lint/hash_compare_by_identity'
280
285
  require_relative 'rubocop/cop/lint/heredoc_method_call_position'
281
286
  require_relative 'rubocop/cop/lint/identity_comparison'
282
287
  require_relative 'rubocop/cop/lint/implicit_string_concatenation'
@@ -306,6 +311,7 @@ require_relative 'rubocop/cop/lint/rand_one'
306
311
  require_relative 'rubocop/cop/lint/redundant_cop_disable_directive'
307
312
  require_relative 'rubocop/cop/lint/redundant_cop_enable_directive'
308
313
  require_relative 'rubocop/cop/lint/redundant_require_statement'
314
+ require_relative 'rubocop/cop/lint/redundant_safe_navigation'
309
315
  require_relative 'rubocop/cop/lint/redundant_splat_expansion'
310
316
  require_relative 'rubocop/cop/lint/redundant_string_coercion'
311
317
  require_relative 'rubocop/cop/lint/redundant_with_index'
@@ -327,11 +333,13 @@ require_relative 'rubocop/cop/lint/shadowing_outer_local_variable'
327
333
  require_relative 'rubocop/cop/lint/struct_new_override'
328
334
  require_relative 'rubocop/cop/lint/suppressed_exception'
329
335
  require_relative 'rubocop/cop/lint/syntax'
336
+ require_relative 'rubocop/cop/lint/to_enum_arguments'
330
337
  require_relative 'rubocop/cop/lint/to_json'
331
338
  require_relative 'rubocop/cop/lint/top_level_return_with_argument'
332
339
  require_relative 'rubocop/cop/lint/trailing_comma_in_attribute_declaration'
333
340
  require_relative 'rubocop/cop/lint/underscore_prefixed_variable_name'
334
341
  require_relative 'rubocop/cop/lint/unified_integer'
342
+ require_relative 'rubocop/cop/lint/unmodified_reduce_accumulator'
335
343
  require_relative 'rubocop/cop/lint/unreachable_code'
336
344
  require_relative 'rubocop/cop/lint/unreachable_loop'
337
345
  require_relative 'rubocop/cop/lint/unused_block_argument'
@@ -381,6 +389,7 @@ require_relative 'rubocop/cop/style/access_modifier_declarations'
381
389
  require_relative 'rubocop/cop/style/accessor_grouping'
382
390
  require_relative 'rubocop/cop/style/alias'
383
391
  require_relative 'rubocop/cop/style/and_or'
392
+ require_relative 'rubocop/cop/style/arguments_forwarding'
384
393
  require_relative 'rubocop/cop/style/array_coercion'
385
394
  require_relative 'rubocop/cop/style/array_join'
386
395
  require_relative 'rubocop/cop/style/ascii_comments'
@@ -396,6 +405,7 @@ require_relative 'rubocop/cop/style/case_like_if'
396
405
  require_relative 'rubocop/cop/style/character_literal'
397
406
  require_relative 'rubocop/cop/style/class_and_module_children'
398
407
  require_relative 'rubocop/cop/style/class_check'
408
+ require_relative 'rubocop/cop/style/class_equality_comparison'
399
409
  require_relative 'rubocop/cop/style/class_methods'
400
410
  require_relative 'rubocop/cop/style/class_methods_definitions'
401
411
  require_relative 'rubocop/cop/style/class_vars'
@@ -415,6 +425,7 @@ require_relative 'rubocop/cop/style/dir'
415
425
  require_relative 'rubocop/cop/style/disable_cops_within_source_code_directive'
416
426
  require_relative 'rubocop/cop/style/documentation_method'
417
427
  require_relative 'rubocop/cop/style/documentation'
428
+ require_relative 'rubocop/cop/style/document_dynamic_eval_definition'
418
429
  require_relative 'rubocop/cop/style/double_cop_disable_directive'
419
430
  require_relative 'rubocop/cop/style/double_negation'
420
431
  require_relative 'rubocop/cop/style/each_for_simple_loop'
@@ -467,8 +478,6 @@ require_relative 'rubocop/cop/style/redundant_fetch_block'
467
478
  require_relative 'rubocop/cop/style/redundant_file_extension_in_require'
468
479
  require_relative 'rubocop/cop/style/redundant_self_assignment'
469
480
  require_relative 'rubocop/cop/style/sole_nested_conditional'
470
- require_relative 'rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses'
471
- require_relative 'rubocop/cop/style/method_call_with_args_parentheses/require_parentheses'
472
481
  require_relative 'rubocop/cop/style/method_called_on_do_end_block'
473
482
  require_relative 'rubocop/cop/style/method_def_parentheses'
474
483
  require_relative 'rubocop/cop/style/min_max'
@@ -552,6 +561,7 @@ require_relative 'rubocop/cop/style/string_literals_in_interpolation'
552
561
  require_relative 'rubocop/cop/style/string_methods'
553
562
  require_relative 'rubocop/cop/style/strip'
554
563
  require_relative 'rubocop/cop/style/struct_inheritance'
564
+ require_relative 'rubocop/cop/style/swap_values'
555
565
  require_relative 'rubocop/cop/style/symbol_array'
556
566
  require_relative 'rubocop/cop/style/symbol_literal'
557
567
  require_relative 'rubocop/cop/style/symbol_proc'
@@ -628,6 +638,7 @@ require_relative 'rubocop/cli/command/execute_runner'
628
638
  require_relative 'rubocop/cli/command/init_dotfile'
629
639
  require_relative 'rubocop/cli/command/show_cops'
630
640
  require_relative 'rubocop/cli/command/version'
641
+ require_relative 'rubocop/config_regeneration'
631
642
  require_relative 'rubocop/options'
632
643
  require_relative 'rubocop/remote_config'
633
644
  require_relative 'rubocop/target_ruby'
@@ -636,3 +647,4 @@ require_relative 'rubocop/yaml_duplication_checker'
636
647
  unless File.exist?("#{__dir__}/../rubocop.gemspec") # Check if we are a gem
637
648
  RuboCop::ResultCache.rubocop_required_features = $LOADED_FEATURES - before_us
638
649
  end
650
+ RuboCop::AST.rubocop_loaded if RuboCop::AST.respond_to?(:rubocop_loaded)
@@ -21,6 +21,7 @@ module RuboCop
21
21
  private
22
22
 
23
23
  def serialize_offense(offense)
24
+ status = :uncorrected if %i[corrected corrected_with_todo].include?(offense.status)
24
25
  {
25
26
  # Calling #to_s here ensures that the serialization works when using
26
27
  # other json serializers such as Oj. Some of these gems do not call
@@ -32,7 +33,7 @@ module RuboCop
32
33
  },
33
34
  message: message(offense),
34
35
  cop_name: offense.cop_name,
35
- status: :uncorrected
36
+ status: status || offense.status
36
37
  }
37
38
  end
38
39
 
@@ -90,7 +90,7 @@ module RuboCop
90
90
  def reset_config_and_auto_gen_file
91
91
  @config_store = ConfigStore.new
92
92
  @config_store.options_config = @options[:config] if @options[:config]
93
- File.open(AUTO_GENERATED_FILE, 'w') {}
93
+ File.open(AUTO_GENERATED_FILE, 'w') {} # create or truncate if exists
94
94
  add_inheritance_from_auto_generated_file(@options[:config])
95
95
  end
96
96
 
@@ -10,7 +10,7 @@ module RuboCop
10
10
 
11
11
  def run
12
12
  puts RuboCop::Version.version(debug: false) if @options[:version]
13
- puts RuboCop::Version.version(debug: true) if @options[:verbose_version]
13
+ puts RuboCop::Version.version(debug: true, env: env) if @options[:verbose_version]
14
14
  end
15
15
  end
16
16
  end
@@ -8,7 +8,7 @@ module RuboCop
8
8
  REDUNDANT_DISABLE = 'Lint/RedundantCopDisableDirective'
9
9
 
10
10
  # @api private
11
- COP_NAME_PATTERN = '([A-Z]\w+/)?(?:[A-Z]\w+)'
11
+ COP_NAME_PATTERN = '([A-Z]\w+/)*(?:[A-Z]\w+)'
12
12
  # @api private
13
13
  COP_NAMES_PATTERN = "(?:#{COP_NAME_PATTERN} , )*#{COP_NAME_PATTERN}"
14
14
  # @api private
@@ -37,6 +37,10 @@ module RuboCop
37
37
  new(hash, path).check
38
38
  end
39
39
 
40
+ def loaded_features
41
+ @loaded_features ||= ConfigLoader.loaded_features
42
+ end
43
+
40
44
  def check
41
45
  deprecation_check do |deprecation_message|
42
46
  warn("#{loaded_path} - #{deprecation_message}")
@@ -35,12 +35,13 @@ module RuboCop
35
35
  end
36
36
 
37
37
  def load_file(file)
38
- path = File.absolute_path(file.is_a?(RemoteConfig) ? file.file : file)
38
+ path = file_path(file)
39
39
 
40
40
  hash = load_yaml_configuration(path)
41
41
 
42
42
  # Resolve requires first in case they define additional cops
43
- resolver.resolve_requires(path, hash)
43
+ loaded_features = resolver.resolve_requires(path, hash)
44
+ add_loaded_features(loaded_features)
44
45
 
45
46
  add_missing_namespaces(path, hash)
46
47
 
@@ -172,8 +173,24 @@ module RuboCop
172
173
  resolver.merge_with_default(config, config_file, unset_nil: unset_nil)
173
174
  end
174
175
 
176
+ def loaded_features
177
+ @loaded_features.flatten.compact
178
+ end
179
+
175
180
  private
176
181
 
182
+ def file_path(file)
183
+ File.absolute_path(file.is_a?(RemoteConfig) ? file.file : file)
184
+ end
185
+
186
+ def add_loaded_features(loaded_features)
187
+ if instance_variable_defined?(:@loaded_features)
188
+ instance_variable_get(:@loaded_features) << loaded_features
189
+ else
190
+ instance_variable_set(:@loaded_features, [loaded_features])
191
+ end
192
+ end
193
+
177
194
  def find_project_dotfile(target_dir)
178
195
  find_file_upwards(DOTFILE, target_dir, project_root)
179
196
  end
@@ -9,11 +9,13 @@ module RuboCop
9
9
  class ConfigLoaderResolver
10
10
  def resolve_requires(path, hash)
11
11
  config_dir = File.dirname(path)
12
- Array(hash.delete('require')).each do |r|
13
- if r.start_with?('.')
14
- require(File.join(config_dir, r))
15
- else
16
- require(r)
12
+ hash.delete('require').tap do |loaded_features|
13
+ Array(loaded_features).each do |feature|
14
+ if feature.start_with?('.')
15
+ require(File.join(config_dir, feature))
16
+ else
17
+ require(feature)
18
+ end
17
19
  end
18
20
  end
19
21
  end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ # This class handles collecting the options for regenerating a TODO file.
5
+ # @api private
6
+ class ConfigRegeneration
7
+ AUTO_GENERATED_FILE = RuboCop::CLI::Command::AutoGenerateConfig::AUTO_GENERATED_FILE
8
+ COMMAND_REGEX = /(?<=`rubocop )(.*?)(?=`)/.freeze
9
+ DEFAULT_OPTIONS = { auto_gen_config: true }.freeze
10
+
11
+ # Get options from the comment in the TODO file, and parse them as options
12
+ def options
13
+ # If there's no existing TODO file, generate one
14
+ return DEFAULT_OPTIONS unless todo_exists?
15
+
16
+ match = generation_command.match(COMMAND_REGEX)
17
+ return DEFAULT_OPTIONS unless match
18
+
19
+ options = match[1].split(' ')
20
+ Options.new.parse(options).first
21
+ end
22
+
23
+ private
24
+
25
+ def todo_exists?
26
+ File.exist?(AUTO_GENERATED_FILE) && !File.empty?(AUTO_GENERATED_FILE)
27
+ end
28
+
29
+ def generation_command
30
+ File.foreach(AUTO_GENERATED_FILE).take(2).last
31
+ end
32
+ end
33
+ end
@@ -18,6 +18,11 @@ module RuboCop
18
18
  # @api private
19
19
  NEW_COPS_VALUES = %w[pending disable enable].freeze
20
20
 
21
+ # @api private
22
+ CONFIG_CHECK_KEYS = %w[Enabled Safe SafeAutoCorrect AutoCorrect].to_set.freeze
23
+ CONFIG_CHECK_DEPARTMENTS = %w[pending override_department].freeze
24
+ private_constant :CONFIG_CHECK_KEYS, :CONFIG_CHECK_DEPARTMENTS
25
+
21
26
  def_delegators :@config, :smart_loaded_path, :for_all_cops
22
27
 
23
28
  def initialize(config)
@@ -202,13 +207,9 @@ module RuboCop
202
207
  hash.each do |key, value|
203
208
  check_cop_config_value(value, key) if value.is_a?(Hash)
204
209
 
205
- next unless %w[Enabled
206
- Safe
207
- SafeAutoCorrect
208
- AutoCorrect].include?(key) && value.is_a?(String)
210
+ next unless CONFIG_CHECK_KEYS.include?(key) && value.is_a?(String)
209
211
 
210
- next if key == 'Enabled' &&
211
- %w[pending override_department].include?(value)
212
+ next if key == 'Enabled' && CONFIG_CHECK_DEPARTMENTS.include?(value)
212
213
 
213
214
  raise ValidationError, msg_not_boolean(parent, key, value)
214
215
  end
@@ -10,37 +10,22 @@ module RuboCop
10
10
  # allow for badge references in source files that omit the department for
11
11
  # RuboCop to infer.
12
12
  class Badge
13
- # Error raised when a badge parse fails.
14
- class InvalidBadge < Error
15
- MSG = 'Invalid badge %<badge>p. ' \
16
- 'Expected `Department/CopName` or `CopName`.'
17
-
18
- def initialize(token)
19
- super(format(MSG, badge: token))
20
- end
21
- end
22
-
23
13
  attr_reader :department, :cop_name
24
14
 
25
15
  def self.for(class_name)
26
- new(*class_name.split('::').last(2))
16
+ parts = class_name.split('::')
17
+ name_deep_enough = parts.length >= 4
18
+ new(name_deep_enough ? parts[2..-1] : parts.last(2))
27
19
  end
28
20
 
29
21
  def self.parse(identifier)
30
- parts = identifier.split('/', 2)
31
-
32
- raise InvalidBadge, identifier if parts.size > 2
33
-
34
- if parts.one?
35
- new(nil, *parts)
36
- else
37
- new(*parts)
38
- end
22
+ new(identifier.split('/'))
39
23
  end
40
24
 
41
- def initialize(department, cop_name)
42
- @department = department.to_sym if department
43
- @cop_name = cop_name
25
+ def initialize(class_name_parts)
26
+ department_parts = class_name_parts[0...-1]
27
+ @department = (department_parts.join('/').to_sym unless department_parts.empty?)
28
+ @cop_name = class_name_parts.last
44
29
  end
45
30
 
46
31
  def ==(other)
@@ -66,7 +51,7 @@ module RuboCop
66
51
  end
67
52
 
68
53
  def with_department(department)
69
- self.class.new(department, cop_name)
54
+ self.class.new([department.to_s.split('/'), cop_name].flatten)
70
55
  end
71
56
  end
72
57
  end
@@ -261,6 +261,21 @@ module RuboCop
261
261
  'they are returned as the result of the investigation'
262
262
  end
263
263
 
264
+ ### Reserved for Commissioner
265
+
266
+ # @api private
267
+ def callbacks_needed
268
+ self.class.callbacks_needed
269
+ end
270
+
271
+ # @api private
272
+ def self.callbacks_needed
273
+ @callbacks_needed ||= public_instance_methods.select do |m|
274
+ m.match?(/^on_|^after_/) &&
275
+ !Base.method_defined?(m) # exclude standard "callbacks" like 'on_begin_investigation'
276
+ end
277
+ end
278
+
264
279
  private
265
280
 
266
281
  ### Reserved for Cop::Cop
@@ -291,7 +306,7 @@ module RuboCop
291
306
  end
292
307
 
293
308
  private_class_method def self.restrict_on_send
294
- @restrict_on_send ||= self::RESTRICT_ON_SEND.to_set.freeze
309
+ @restrict_on_send ||= self::RESTRICT_ON_SEND.to_a.freeze
295
310
  end
296
311
 
297
312
  # Called before any investigation
@@ -25,6 +25,16 @@ module RuboCop
25
25
  #
26
26
  # # good
27
27
  # gem 'rubocop', groups: [:development, :test]
28
+ #
29
+ # # good - conditional declaration
30
+ # if Dir.exist?(local)
31
+ # gem 'rubocop', path: local
32
+ # elsif ENV['RUBOCOP_VERSION'] == 'master'
33
+ # gem 'rubocop', git: 'https://github.com/rubocop-hq/rubocop.git'
34
+ # else
35
+ # gem 'rubocop', '~> 0.90.0'
36
+ # end
37
+ #
28
38
  class DuplicatedGem < Cop
29
39
  include RangeHelp
30
40
 
@@ -53,11 +63,21 @@ module RuboCop
53
63
  gem_declarations(processed_source.ast)
54
64
  .group_by(&:first_argument)
55
65
  .values
56
- .select { |nodes| nodes.size > 1 && !condition?(nodes) }
66
+ .select { |nodes| nodes.size > 1 && !conditional_declaration?(nodes) }
57
67
  end
58
68
 
59
- def condition?(nodes)
60
- nodes[0].parent&.if_type? && nodes[0].parent == nodes[1].parent
69
+ def conditional_declaration?(nodes)
70
+ parent = nodes[0].parent
71
+ return false unless parent&.if_type? || parent&.when_type?
72
+
73
+ root_conditional_node = parent.if_type? ? parent : parent.parent
74
+ nodes.all? { |node| within_conditional?(node, root_conditional_node) }
75
+ end
76
+
77
+ def within_conditional?(node, conditional_node)
78
+ conditional_node.branches.any? do |branch|
79
+ branch == node || branch.child_nodes.include?(node)
80
+ end
61
81
  end
62
82
 
63
83
  def register_offense(node, gem_name, line_of_first_occurrence)
@@ -7,7 +7,7 @@ module RuboCop
7
7
  class Commissioner
8
8
  include RuboCop::AST::Traversal
9
9
 
10
- RESTRICTED_CALLBACKS = %i[on_send on_csend].freeze
10
+ RESTRICTED_CALLBACKS = %i[on_send on_csend after_send after_csend].freeze
11
11
  private_constant :RESTRICTED_CALLBACKS
12
12
 
13
13
  # How a Commissioner returns the results of the investigation
@@ -45,8 +45,7 @@ module RuboCop
45
45
  @cops = cops
46
46
  @forces = forces
47
47
  @options = options
48
- @callbacks = Hash.new { |h, k| h[k] = cops_callbacks_for(k) }
49
- @restricted_map = {}
48
+ initialize_callbacks
50
49
 
51
50
  reset
52
51
  end
@@ -61,16 +60,18 @@ module RuboCop
61
60
  method_name = :"on_#{node_type}"
62
61
  next unless method_defined?(method_name)
63
62
 
64
- if RESTRICTED_CALLBACKS.include?(method_name)
65
- trigger_restricted = "trigger_restricted_cops(:on_#{node_type}, node)"
66
- end
63
+ # Hacky: Comment-out code as needed
64
+ r = '#' unless RESTRICTED_CALLBACKS.include?(method_name) # has Restricted?
65
+ c = '#' if NO_CHILD_NODES.include?(node_type) # has Children?
67
66
 
68
67
  class_eval(<<~RUBY, __FILE__, __LINE__ + 1)
69
- def on_#{node_type}(node)
70
- trigger_responding_cops(:on_#{node_type}, node)
71
- #{trigger_restricted}
72
- #{'super(node)' unless NO_CHILD_NODES.include?(node_type)}
73
- end
68
+ def on_#{node_type}(node) # def on_send(node)
69
+ trigger_responding_cops(:on_#{node_type}, node) # trigger_responding_cops(:on_send, node)
70
+ #{r} trigger_restricted_cops(:on_#{node_type}, node) # trigger_restricted_cops(:on_send, node)
71
+ #{c} super(node) # super(node)
72
+ #{c} trigger_responding_cops(:after_#{node_type}, node) # trigger_responding_cops(:after_send, node)
73
+ #{c}#{r} trigger_restricted_cops(:after_#{node_type}, node) # trigger_restricted_cops(:after_send, node)
74
+ end # end
74
75
  RUBY
75
76
  end
76
77
 
@@ -94,9 +95,9 @@ module RuboCop
94
95
  private
95
96
 
96
97
  def trigger_responding_cops(callback, node)
97
- @callbacks[callback].each do |cop|
98
+ @callbacks[callback]&.each do |cop|
98
99
  with_cop_error_handling(cop, node) do
99
- cop.send(callback, node)
100
+ cop.public_send(callback, node)
100
101
  end
101
102
  end
102
103
  end
@@ -105,21 +106,34 @@ module RuboCop
105
106
  @errors = []
106
107
  end
107
108
 
108
- def cops_callbacks_for(callback)
109
- callbacks = @cops.select do |cop|
110
- cop.respond_to?(callback)
111
- end
112
- if RESTRICTED_CALLBACKS.include?(callback)
113
- @restricted_map[callback] = restricted_map(callbacks)
109
+ def initialize_callbacks
110
+ @callbacks = build_callbacks(@cops)
111
+ @restricted_map = restrict_callbacks(@callbacks)
112
+ end
113
+
114
+ def build_callbacks(cops)
115
+ callbacks = {}
116
+ cops.each do |cop|
117
+ cop.callbacks_needed.each do |callback|
118
+ (callbacks[callback] ||= []) << cop
119
+ end
114
120
  end
115
121
  callbacks
116
122
  end
117
123
 
124
+ def restrict_callbacks(callbacks)
125
+ restricted = {}
126
+ RESTRICTED_CALLBACKS.each do |callback|
127
+ restricted[callback] = restricted_map(callbacks[callback])
128
+ end
129
+ restricted
130
+ end
131
+
118
132
  def trigger_restricted_cops(event, node)
119
133
  name = node.method_name
120
- @restricted_map.fetch(event)[name]&.each do |cop|
134
+ @restricted_map[event][name]&.each do |cop|
121
135
  with_cop_error_handling(cop, node) do
122
- cop.send(event, node)
136
+ cop.public_send(event, node)
123
137
  end
124
138
  end
125
139
  end
@@ -127,7 +141,7 @@ module RuboCop
127
141
  # Note: mutates `callbacks` in place
128
142
  def restricted_map(callbacks)
129
143
  map = {}
130
- callbacks.select! do |cop|
144
+ callbacks&.select! do |cop|
131
145
  restrictions = cop.class.send :restrict_on_send
132
146
  restrictions.each do |name|
133
147
  (map[name] ||= []) << cop