rubocop 1.22.2 → 1.24.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (95) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -2
  3. data/config/default.yml +87 -5
  4. data/lib/rubocop/cli/command/auto_genenerate_config.rb +1 -1
  5. data/lib/rubocop/cli/command/init_dotfile.rb +1 -1
  6. data/lib/rubocop/cli/command/show_docs_url.rb +48 -0
  7. data/lib/rubocop/cli/command/suggest_extensions.rb +1 -1
  8. data/lib/rubocop/cli.rb +1 -0
  9. data/lib/rubocop/config_loader_resolver.rb +1 -1
  10. data/lib/rubocop/cop/bundler/duplicated_gem.rb +1 -1
  11. data/lib/rubocop/cop/correctors/each_to_for_corrector.rb +1 -1
  12. data/lib/rubocop/cop/correctors/if_then_corrector.rb +55 -0
  13. data/lib/rubocop/cop/documentation.rb +19 -2
  14. data/lib/rubocop/cop/gemspec/date_assignment.rb +2 -10
  15. data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +1 -10
  16. data/lib/rubocop/cop/gemspec/require_mfa.rb +144 -0
  17. data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +3 -10
  18. data/lib/rubocop/cop/generator.rb +1 -1
  19. data/lib/rubocop/cop/internal_affairs/redundant_method_dispatch_node.rb +47 -0
  20. data/lib/rubocop/cop/internal_affairs/undefined_config.rb +3 -1
  21. data/lib/rubocop/cop/internal_affairs.rb +1 -0
  22. data/lib/rubocop/cop/layout/block_alignment.rb +3 -3
  23. data/lib/rubocop/cop/layout/comment_indentation.rb +31 -2
  24. data/lib/rubocop/cop/layout/dot_position.rb +9 -1
  25. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +22 -1
  26. data/lib/rubocop/cop/layout/hash_alignment.rb +1 -1
  27. data/lib/rubocop/cop/layout/space_after_colon.rb +1 -1
  28. data/lib/rubocop/cop/layout/space_before_first_arg.rb +4 -0
  29. data/lib/rubocop/cop/layout/space_in_lambda_literal.rb +11 -5
  30. data/lib/rubocop/cop/lint/ambiguous_range.rb +2 -2
  31. data/lib/rubocop/cop/lint/constant_definition_in_block.rb +1 -1
  32. data/lib/rubocop/cop/lint/deprecated_class_methods.rb +16 -4
  33. data/lib/rubocop/cop/lint/deprecated_constants.rb +3 -2
  34. data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +6 -0
  35. data/lib/rubocop/cop/lint/each_with_object_argument.rb +1 -1
  36. data/lib/rubocop/cop/lint/incompatible_io_select_with_fiber_scheduler.rb +4 -0
  37. data/lib/rubocop/cop/lint/number_conversion.rb +5 -2
  38. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +7 -4
  39. data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +117 -0
  40. data/lib/rubocop/cop/metrics/block_length.rb +1 -0
  41. data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +0 -9
  42. data/lib/rubocop/cop/metrics/method_length.rb +1 -0
  43. data/lib/rubocop/cop/metrics/module_length.rb +1 -1
  44. data/lib/rubocop/cop/metrics/parameter_lists.rb +1 -1
  45. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +1 -1
  46. data/lib/rubocop/cop/metrics/utils/repeated_attribute_discount.rb +1 -1
  47. data/lib/rubocop/cop/mixin/enforce_superclass.rb +5 -0
  48. data/lib/rubocop/cop/mixin/gemspec_help.rb +30 -0
  49. data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +4 -3
  50. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +56 -0
  51. data/lib/rubocop/cop/mixin/string_literals_help.rb +1 -5
  52. data/lib/rubocop/cop/naming/block_forwarding.rb +107 -0
  53. data/lib/rubocop/cop/naming/file_name.rb +37 -4
  54. data/lib/rubocop/cop/security/open.rb +11 -1
  55. data/lib/rubocop/cop/style/character_literal.rb +8 -1
  56. data/lib/rubocop/cop/style/collection_compact.rb +31 -13
  57. data/lib/rubocop/cop/style/combinable_loops.rb +2 -2
  58. data/lib/rubocop/cop/style/documentation.rb +1 -1
  59. data/lib/rubocop/cop/style/empty_case_condition.rb +10 -0
  60. data/lib/rubocop/cop/style/empty_method.rb +1 -1
  61. data/lib/rubocop/cop/style/file_read.rb +112 -0
  62. data/lib/rubocop/cop/style/file_write.rb +124 -0
  63. data/lib/rubocop/cop/style/format_string_token.rb +2 -1
  64. data/lib/rubocop/cop/style/hash_conversion.rb +2 -1
  65. data/lib/rubocop/cop/style/hash_syntax.rb +22 -0
  66. data/lib/rubocop/cop/style/hash_transform_keys.rb +6 -6
  67. data/lib/rubocop/cop/style/hash_transform_values.rb +6 -6
  68. data/lib/rubocop/cop/style/if_inside_else.rb +15 -0
  69. data/lib/rubocop/cop/style/map_to_hash.rb +68 -0
  70. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +13 -0
  71. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +3 -1
  72. data/lib/rubocop/cop/style/method_def_parentheses.rb +17 -13
  73. data/lib/rubocop/cop/style/numeric_literals.rb +10 -1
  74. data/lib/rubocop/cop/style/one_line_conditional.rb +18 -39
  75. data/lib/rubocop/cop/style/open_struct_use.rb +69 -0
  76. data/lib/rubocop/cop/style/parentheses_around_condition.rb +12 -2
  77. data/lib/rubocop/cop/style/quoted_symbols.rb +11 -1
  78. data/lib/rubocop/cop/style/redundant_interpolation.rb +17 -3
  79. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +5 -1
  80. data/lib/rubocop/cop/style/redundant_self.rb +1 -1
  81. data/lib/rubocop/cop/style/safe_navigation.rb +1 -5
  82. data/lib/rubocop/cop/style/select_by_regexp.rb +4 -3
  83. data/lib/rubocop/cop/style/single_line_block_params.rb +2 -2
  84. data/lib/rubocop/cop/style/sole_nested_conditional.rb +3 -1
  85. data/lib/rubocop/cop/team.rb +1 -1
  86. data/lib/rubocop/cop/util.rb +9 -1
  87. data/lib/rubocop/formatter/html_formatter.rb +5 -2
  88. data/lib/rubocop/formatter/json_formatter.rb +4 -1
  89. data/lib/rubocop/options.rb +6 -1
  90. data/lib/rubocop/remote_config.rb +2 -4
  91. data/lib/rubocop/result_cache.rb +1 -1
  92. data/lib/rubocop/version.rb +1 -1
  93. data/lib/rubocop/yaml_duplication_checker.rb +1 -1
  94. data/lib/rubocop.rb +11 -0
  95. metadata +18 -5
@@ -45,7 +45,7 @@ module RuboCop
45
45
 
46
46
  message = message(node)
47
47
  add_offense(node, message: message) do |corrector|
48
- corrector.replace(node, replacement(node))
48
+ autocorrect(corrector, node)
49
49
  end
50
50
  end
51
51
 
@@ -55,55 +55,30 @@ module RuboCop
55
55
  format(MSG, keyword: node.keyword)
56
56
  end
57
57
 
58
- def replacement(node)
58
+ def autocorrect(corrector, node)
59
59
  if always_multiline? || cannot_replace_to_ternary?(node)
60
- multiline_replacement(node)
60
+ IfThenCorrector.new(node, indentation: indentation_width).call(corrector)
61
61
  else
62
- replaced_node = ternary_replacement(node)
63
- return replaced_node unless node.parent
64
- return "(#{replaced_node})" if %i[and or].include?(node.parent.type)
65
- return "(#{replaced_node})" if node.parent.send_type? && node.parent.operator_method?
66
-
67
- replaced_node
62
+ corrector.replace(node, ternary_correction(node))
68
63
  end
69
64
  end
70
65
 
71
- def always_multiline?
72
- @config.for_cop('Style/OneLineConditional')['AlwaysCorrectToMultiline']
73
- end
66
+ def ternary_correction(node)
67
+ replaced_node = ternary_replacement(node)
74
68
 
75
- def cannot_replace_to_ternary?(node)
76
- node.elsif_conditional?
77
- end
69
+ return replaced_node unless node.parent
70
+ return "(#{replaced_node})" if %i[and or].include?(node.parent.type)
71
+ return "(#{replaced_node})" if node.parent.send_type? && node.parent.operator_method?
78
72
 
79
- def multiline_replacement(node, indentation = nil)
80
- indentation = ' ' * node.source_range.column if indentation.nil?
81
- if_branch_source = node.if_branch&.source || 'nil'
82
- elsif_indentation = indentation if node.respond_to?(:elsif?) && node.elsif?
83
- if_branch = <<~RUBY
84
- #{elsif_indentation}#{node.keyword} #{node.condition.source}
85
- #{indentation}#{branch_body_indentation}#{if_branch_source}
86
- RUBY
87
- else_branch = else_branch_to_multiline(node.else_branch, indentation)
88
- if_branch + else_branch
73
+ replaced_node
89
74
  end
90
75
 
91
- def else_branch_to_multiline(else_branch, indentation)
92
- if else_branch.nil?
93
- 'end'
94
- elsif else_branch.if_type? && else_branch.elsif?
95
- multiline_replacement(else_branch, indentation)
96
- else
97
- <<~RUBY.chomp
98
- #{indentation}else
99
- #{indentation}#{branch_body_indentation}#{else_branch.source}
100
- #{indentation}end
101
- RUBY
102
- end
76
+ def always_multiline?
77
+ @config.for_cop('Style/OneLineConditional')['AlwaysCorrectToMultiline']
103
78
  end
104
79
 
105
- def branch_body_indentation
106
- ' ' * (@config.for_cop('Layout/IndentationWidth')['Width'] || 2)
80
+ def cannot_replace_to_ternary?(node)
81
+ node.elsif_conditional?
107
82
  end
108
83
 
109
84
  def ternary_replacement(node)
@@ -141,6 +116,10 @@ module RuboCop
141
116
 
142
117
  node.respond_to?(:arguments?) && node.arguments? && !node.parenthesized_call?
143
118
  end
119
+
120
+ def indentation_width
121
+ @config.for_cop('Layout/IndentationWidth')['Width']
122
+ end
144
123
  end
145
124
  end
146
125
  end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Style
6
+ # This cop flags uses of OpenStruct, as it is now officially discouraged
7
+ # to be used for performance, version compatibility, and potential security issues.
8
+ #
9
+ # @safety
10
+ #
11
+ # Note that this cop may flag false positives; for instance, the following legal
12
+ # use of a hand-rolled `OpenStruct` type would be considered an offense:
13
+ #
14
+ # ```
15
+ # module MyNamespace
16
+ # class OpenStruct # not the OpenStruct we're looking for
17
+ # end
18
+ #
19
+ # def new_struct
20
+ # OpenStruct.new # resolves to MyNamespace::OpenStruct
21
+ # end
22
+ # end
23
+ # ```
24
+ #
25
+ # @example
26
+ #
27
+ # # bad
28
+ # point = OpenStruct.new(x: 0, y: 1)
29
+ #
30
+ # # good
31
+ # Point = Struct.new(:x, :y)
32
+ # point = Point.new(0, 1)
33
+ #
34
+ # # also good
35
+ # point = { x: 0, y: 1 }
36
+ #
37
+ # # bad
38
+ # test_double = OpenStruct.new(a: 'b')
39
+ #
40
+ # # good (assumes test using rspec-mocks)
41
+ # test_double = double
42
+ # allow(test_double).to receive(:a).and_return('b')
43
+ #
44
+ class OpenStructUse < Base
45
+ MSG = 'Avoid using `OpenStruct`; use `Struct`, `Hash`, a class or test doubles instead.'
46
+
47
+ # @!method uses_open_struct?(node)
48
+ def_node_matcher :uses_open_struct?, <<-PATTERN
49
+ (const {nil? (cbase)} :OpenStruct)
50
+ PATTERN
51
+
52
+ def on_const(node)
53
+ return unless uses_open_struct?(node)
54
+ return if custom_class_or_module_definition?(node)
55
+
56
+ add_offense(node)
57
+ end
58
+
59
+ private
60
+
61
+ def custom_class_or_module_definition?(node)
62
+ parent = node.parent
63
+
64
+ (parent.class_type? || parent.module_type?) && node.left_siblings.empty?
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -56,6 +56,7 @@ module RuboCop
56
56
  class ParenthesesAroundCondition < Base
57
57
  include SafeAssignment
58
58
  include Parentheses
59
+ include RangeHelp
59
60
  extend AutoCorrector
60
61
 
61
62
  def on_if(node)
@@ -73,13 +74,14 @@ module RuboCop
73
74
 
74
75
  # @!method control_op_condition(node)
75
76
  def_node_matcher :control_op_condition, <<~PATTERN
76
- (begin $_ ...)
77
+ (begin $_ $...)
77
78
  PATTERN
78
79
 
79
80
  def process_control_op(node)
80
81
  cond = node.condition
81
82
 
82
- control_op_condition(cond) do |first_child|
83
+ control_op_condition(cond) do |first_child, rest_children|
84
+ return if semicolon_separated_expressions?(first_child, rest_children)
83
85
  return if modifier_op?(first_child)
84
86
  return if parens_allowed?(cond)
85
87
 
@@ -90,6 +92,14 @@ module RuboCop
90
92
  end
91
93
  end
92
94
 
95
+ def semicolon_separated_expressions?(first_exp, rest_exps)
96
+ return false unless (second_exp = rest_exps.first)
97
+
98
+ range = range_between(first_exp.source_range.end_pos, second_exp.source_range.begin_pos)
99
+
100
+ range.source.include?(';')
101
+ end
102
+
93
103
  def modifier_op?(node)
94
104
  return false if node.if_type? && node.ternary?
95
105
  return true if node.rescue_type?
@@ -46,7 +46,7 @@ module RuboCop
46
46
 
47
47
  message = style == :single_quotes ? MSG_SINGLE : MSG_DOUBLE
48
48
 
49
- if wrong_quotes?(node)
49
+ if wrong_quotes?(node) || invalid_double_quotes?(node.source)
50
50
  add_offense(node, message: message) do |corrector|
51
51
  opposite_style_detected
52
52
  autocorrect(corrector, node)
@@ -58,6 +58,16 @@ module RuboCop
58
58
 
59
59
  private
60
60
 
61
+ def invalid_double_quotes?(source)
62
+ return false unless style == :double_quotes
63
+
64
+ # The string needs single quotes if:
65
+ # 1. It contains a double quote
66
+ # 2. It contains text that would become an escape sequence with double quotes
67
+ # 3. It contains text that would become an interpolation with double quotes
68
+ !/" | (?<!\\)\\[aAbcdefkMnprsStuUxzZ0-7] | \#[@{$]/x.match?(source)
69
+ end
70
+
61
71
  def autocorrect(corrector, node)
62
72
  str = if hash_colon_key?(node)
63
73
  # strip quotes
@@ -82,10 +82,20 @@ module RuboCop
82
82
  end
83
83
 
84
84
  def autocorrect_single_variable_interpolation(corrector, embedded_node, node)
85
- variable_loc = embedded_node.children.first.loc
86
- replacement = "#{variable_loc.expression.source}.to_s"
85
+ embedded_var = embedded_node.children.first
87
86
 
88
- corrector.replace(node, replacement)
87
+ source = if require_parentheses?(embedded_var)
88
+ receiver = range_between(
89
+ embedded_var.loc.expression.begin_pos, embedded_var.loc.selector.end_pos
90
+ )
91
+ arguments = embedded_var.arguments.map(&:source).join(', ')
92
+
93
+ "#{receiver.source}(#{arguments})"
94
+ else
95
+ embedded_var.source
96
+ end
97
+
98
+ corrector.replace(node, "#{source}.to_s")
89
99
  end
90
100
 
91
101
  def autocorrect_other(corrector, embedded_node, node)
@@ -97,6 +107,10 @@ module RuboCop
97
107
  corrector.replace(embedded_loc.begin, '(')
98
108
  corrector.replace(embedded_loc.end, ').to_s')
99
109
  end
110
+
111
+ def require_parentheses?(node)
112
+ node.send_type? && !node.arguments.count.zero? && !node.parenthesized_call?
113
+ end
100
114
  end
101
115
  end
102
116
  end
@@ -80,7 +80,11 @@ module RuboCop
80
80
  end
81
81
 
82
82
  def without_character_class(loc)
83
- loc.source[1..-2]
83
+ without_character_class = loc.source[1..-2]
84
+
85
+ # Adds `\` to prevent auto-correction that changes to an interpolated string when `[#]`.
86
+ # e.g. From `/[#]{0}/` to `/#{0}/`
87
+ loc.source == '[#]' ? "\\#{without_character_class}" : without_character_class
84
88
  end
85
89
 
86
90
  def whitespace_in_free_space_mode?(node, elem)
@@ -53,7 +53,7 @@ module RuboCop
53
53
  yield __FILE__ __LINE__ __ENCODING__].freeze
54
54
 
55
55
  def self.autocorrect_incompatible_with
56
- [ColonMethodCall]
56
+ [ColonMethodCall, Layout::DotPosition]
57
57
  end
58
58
 
59
59
  def initialize(config = nil, options = nil)
@@ -218,11 +218,7 @@ module RuboCop
218
218
  def find_matching_receiver_invocation(method_chain, checked_variable)
219
219
  return nil unless method_chain
220
220
 
221
- receiver = if method_chain.block_type?
222
- method_chain.send_node.receiver
223
- else
224
- method_chain.receiver
225
- end
221
+ receiver = method_chain.receiver
226
222
 
227
223
  return receiver if receiver == checked_variable
228
224
 
@@ -85,7 +85,7 @@ module RuboCop
85
85
  return unless (regexp_method_send_node = extract_send_node(block_node))
86
86
  return if match_predicate_without_receiver?(regexp_method_send_node)
87
87
 
88
- regexp = find_regexp(regexp_method_send_node)
88
+ regexp = find_regexp(regexp_method_send_node, block_node)
89
89
  register_offense(node, block_node, regexp)
90
90
  end
91
91
 
@@ -119,10 +119,11 @@ module RuboCop
119
119
  regexp_method_send_node
120
120
  end
121
121
 
122
- def find_regexp(node)
122
+ def find_regexp(node, block)
123
123
  return node.child_nodes.first if node.match_with_lvasgn_type?
124
124
 
125
- if node.receiver.lvar_type?
125
+ if node.receiver.lvar_type? &&
126
+ (block.numblock_type? || node.receiver.source == block.arguments.first.source)
126
127
  node.first_argument
127
128
  elsif node.first_argument.lvar_type?
128
129
  node.receiver
@@ -39,7 +39,7 @@ module RuboCop
39
39
  return unless eligible_method?(node)
40
40
  return unless eligible_arguments?(node)
41
41
 
42
- method_name = node.send_node.method_name
42
+ method_name = node.method_name
43
43
  return if args_match?(method_name, node.arguments)
44
44
 
45
45
  preferred_block_arguments = build_preferred_arguments_map(node, target_args(method_name))
@@ -81,7 +81,7 @@ module RuboCop
81
81
  end
82
82
 
83
83
  def eligible_method?(node)
84
- node.send_node.receiver && method_names.include?(node.send_node.method_name)
84
+ node.receiver && method_names.include?(node.method_name)
85
85
  end
86
86
 
87
87
  def methods
@@ -82,7 +82,9 @@ module RuboCop
82
82
  end
83
83
 
84
84
  def autocorrect(corrector, node, if_branch)
85
- corrector.wrap(node.condition, '(', ')') if node.condition.or_type?
85
+ if node.condition.or_type? || node.condition.assignment?
86
+ corrector.wrap(node.condition, '(', ')')
87
+ end
86
88
 
87
89
  correct_from_unless_to_if(corrector, node) if node.unless?
88
90
 
@@ -131,7 +131,7 @@ module RuboCop
131
131
  @options[:stdin] = new_source
132
132
  else
133
133
  filename = processed_source.buffer.name
134
- File.open(filename, 'w') { |f| f.write(new_source) }
134
+ File.write(filename, new_source)
135
135
  end
136
136
  @updated_source_file = true
137
137
  end
@@ -30,8 +30,15 @@ module RuboCop
30
30
  node.loc.respond_to?(:end) && node.loc.end && node.loc.end.is?(')')
31
31
  end
32
32
 
33
+ # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
33
34
  def add_parentheses(node, corrector)
34
- if !node.respond_to?(:arguments)
35
+ if node.args_type?
36
+ arguments_range = node.source_range
37
+ args_with_space = range_with_surrounding_space(range: arguments_range, side: :left)
38
+ leading_space = range_between(args_with_space.begin_pos, arguments_range.begin_pos)
39
+ corrector.replace(leading_space, '(')
40
+ corrector.insert_after(arguments_range, ')')
41
+ elsif !node.respond_to?(:arguments)
35
42
  corrector.wrap(node, '(', ')')
36
43
  elsif node.arguments.empty?
37
44
  corrector.insert_after(node, '()')
@@ -43,6 +50,7 @@ module RuboCop
43
50
  corrector.insert_after(args_end(node), ')')
44
51
  end
45
52
  end
53
+ # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
46
54
 
47
55
  def args_begin(node)
48
56
  loc = node.loc
@@ -23,12 +23,15 @@ module RuboCop
23
23
  end
24
24
  end
25
25
 
26
+ Summary = Struct.new(:offense_count, :inspected_files, :target_files, keyword_init: true)
27
+ FileOffenses = Struct.new(:path, :offenses, keyword_init: true)
28
+
26
29
  attr_reader :files, :summary
27
30
 
28
31
  def initialize(output, options = {})
29
32
  super
30
33
  @files = []
31
- @summary = OpenStruct.new(offense_count: 0)
34
+ @summary = Summary.new(offense_count: 0)
32
35
  end
33
36
 
34
37
  def started(target_files)
@@ -36,7 +39,7 @@ module RuboCop
36
39
  end
37
40
 
38
41
  def file_finished(file, offenses)
39
- files << OpenStruct.new(path: file, offenses: offenses)
42
+ files << FileOffenses.new(path: file, offenses: offenses)
40
43
  summary.offense_count += offenses.count
41
44
  end
42
45
 
@@ -59,12 +59,15 @@ module RuboCop
59
59
  end
60
60
 
61
61
  # TODO: Consider better solution for Offense#real_column.
62
+ # The minimum value of `start_column: real_column` is 1.
63
+ # So, the minimum value of `last_column` should be 1.
64
+ # And non-zero value of `last_column` should be used as is.
62
65
  def hash_for_location(offense)
63
66
  {
64
67
  start_line: offense.line,
65
68
  start_column: offense.real_column,
66
69
  last_line: offense.last_line,
67
- last_column: offense.last_column,
70
+ last_column: offense.last_column.zero? ? 1 : offense.last_column,
68
71
  length: offense.location.length,
69
72
  # `line` and `column` exist for compatibility.
70
73
  # Use `start_line` and `start_column` instead.
@@ -15,7 +15,7 @@ module RuboCop
15
15
  'root of the project. RuboCop will use this path to determine which ' \
16
16
  'cops are enabled (via eg. Include/Exclude), and so that certain cops ' \
17
17
  'like Naming/FileName can be checked.'
18
- EXITING_OPTIONS = %i[version verbose_version show_cops].freeze
18
+ EXITING_OPTIONS = %i[version verbose_version show_cops show_docs_url].freeze
19
19
  DEFAULT_MAXIMUM_EXCLUSION_ITEMS = 15
20
20
 
21
21
  def initialize
@@ -188,6 +188,9 @@ module RuboCop
188
188
  option(opts, '--show-cops [COP1,COP2,...]') do |list|
189
189
  @options[:show_cops] = list.nil? ? [] : list.split(',')
190
190
  end
191
+ option(opts, '--show-docs-url [COP1,COP2,...]') do |list|
192
+ @options[:show_docs_url] = list.nil? ? [] : list.split(',')
193
+ end
191
194
  end
192
195
  end
193
196
 
@@ -475,6 +478,8 @@ module RuboCop
475
478
  show_cops: ['Shows the given cops, or all cops by',
476
479
  'default, and their configurations for the',
477
480
  'current directory.'],
481
+ show_docs_url: ['Display url to documentation for the given',
482
+ 'cops, or base url by default.'],
478
483
  fail_fast: ['Inspect files in order of modification',
479
484
  'time and stop after the first file',
480
485
  'containing offenses.'],
@@ -23,9 +23,7 @@ module RuboCop
23
23
  next if response.is_a?(Net::HTTPNotModified)
24
24
  next if response.is_a?(SocketError)
25
25
 
26
- File.open cache_path, 'w' do |io|
27
- io.write response.body
28
- end
26
+ File.write(cache_path, response.body)
29
27
  end
30
28
 
31
29
  cache_path
@@ -33,7 +31,7 @@ module RuboCop
33
31
 
34
32
  def inherit_from_remote(file, path)
35
33
  new_uri = @uri.dup
36
- new_uri.path.gsub!(%r{/[^/]*$}, "/#{file}")
34
+ new_uri.path.gsub!(%r{/[^/]*$}, "/#{file.delete_prefix('./')}")
37
35
  RemoteConfig.new(new_uri.to_s, File.dirname(path))
38
36
  end
39
37
 
@@ -179,7 +179,7 @@ module RuboCop
179
179
  .select { |path| File.file?(path) }
180
180
  .sort!
181
181
  .each do |path|
182
- content = File.open(path, 'rb', &:read)
182
+ content = File.binread(path)
183
183
  digest << Zlib.crc32(content).to_s # mtime not reliable
184
184
  end
185
185
  digest << RuboCop::Version::STRING << RuboCop::AST::Version::STRING
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  # This module holds the RuboCop version information.
5
5
  module Version
6
- STRING = '1.22.2'
6
+ STRING = '1.24.1'
7
7
 
8
8
  MSG = '%<version>s (using Parser %<parser_version>s, '\
9
9
  'rubocop-ast %<rubocop_ast_version>s, ' \
@@ -23,7 +23,7 @@ module RuboCop
23
23
  when Psych::Nodes::Mapping
24
24
  tree.children.each_slice(2).with_object([]) do |(key, value), keys|
25
25
  exist = keys.find { |key2| key2.value == key.value }
26
- on_duplicated.call(exist, key) if exist
26
+ yield(exist, key) if exist
27
27
  keys << key
28
28
  traverse(value, &on_duplicated)
29
29
  end
data/lib/rubocop.rb CHANGED
@@ -83,6 +83,7 @@ require_relative 'rubocop/cop/mixin/enforce_superclass'
83
83
  require_relative 'rubocop/cop/mixin/first_element_line_break'
84
84
  require_relative 'rubocop/cop/mixin/frozen_string_literal'
85
85
  require_relative 'rubocop/cop/mixin/gem_declaration'
86
+ require_relative 'rubocop/cop/mixin/gemspec_help'
86
87
  require_relative 'rubocop/cop/mixin/hash_alignment_styles'
87
88
  require_relative 'rubocop/cop/mixin/hash_transform_method'
88
89
  require_relative 'rubocop/cop/mixin/ignored_pattern'
@@ -93,6 +94,7 @@ require_relative 'rubocop/cop/mixin/line_length_help'
93
94
  require_relative 'rubocop/cop/mixin/match_range'
94
95
  require_relative 'rubocop/cop/metrics/utils/repeated_csend_discount'
95
96
  require_relative 'rubocop/cop/metrics/utils/repeated_attribute_discount'
97
+ require_relative 'rubocop/cop/mixin/hash_shorthand_syntax'
96
98
  require_relative 'rubocop/cop/mixin/method_complexity'
97
99
  require_relative 'rubocop/cop/mixin/method_preference'
98
100
  require_relative 'rubocop/cop/mixin/min_body_length'
@@ -138,6 +140,7 @@ require_relative 'rubocop/cop/correctors/condition_corrector'
138
140
  require_relative 'rubocop/cop/correctors/each_to_for_corrector'
139
141
  require_relative 'rubocop/cop/correctors/empty_line_corrector'
140
142
  require_relative 'rubocop/cop/correctors/for_to_each_corrector'
143
+ require_relative 'rubocop/cop/correctors/if_then_corrector'
141
144
  require_relative 'rubocop/cop/correctors/lambda_literal_to_method_corrector'
142
145
  require_relative 'rubocop/cop/correctors/line_break_corrector'
143
146
  require_relative 'rubocop/cop/correctors/multiline_literal_brace_corrector'
@@ -160,6 +163,7 @@ require_relative 'rubocop/cop/bundler/ordered_gems'
160
163
  require_relative 'rubocop/cop/gemspec/date_assignment'
161
164
  require_relative 'rubocop/cop/gemspec/duplicated_assignment'
162
165
  require_relative 'rubocop/cop/gemspec/ordered_dependencies'
166
+ require_relative 'rubocop/cop/gemspec/require_mfa'
163
167
  require_relative 'rubocop/cop/gemspec/required_ruby_version'
164
168
  require_relative 'rubocop/cop/gemspec/ruby_version_globals_usage'
165
169
 
@@ -382,6 +386,7 @@ require_relative 'rubocop/cop/lint/useless_access_modifier'
382
386
  require_relative 'rubocop/cop/lint/useless_assignment'
383
387
  require_relative 'rubocop/cop/lint/useless_else_without_rescue'
384
388
  require_relative 'rubocop/cop/lint/useless_method_definition'
389
+ require_relative 'rubocop/cop/lint/useless_ruby2_keywords'
385
390
  require_relative 'rubocop/cop/lint/useless_setter_call'
386
391
  require_relative 'rubocop/cop/lint/useless_times'
387
392
  require_relative 'rubocop/cop/lint/void'
@@ -402,6 +407,7 @@ require_relative 'rubocop/cop/metrics/perceived_complexity'
402
407
 
403
408
  require_relative 'rubocop/cop/naming/accessor_method_name'
404
409
  require_relative 'rubocop/cop/naming/ascii_identifiers'
410
+ require_relative 'rubocop/cop/naming/block_forwarding'
405
411
  require_relative 'rubocop/cop/naming/block_parameter_name'
406
412
  require_relative 'rubocop/cop/naming/class_and_module_camel_case'
407
413
  require_relative 'rubocop/cop/naming/constant_name'
@@ -478,6 +484,8 @@ require_relative 'rubocop/cop/style/even_odd'
478
484
  require_relative 'rubocop/cop/style/expand_path_arguments'
479
485
  require_relative 'rubocop/cop/style/explicit_block_argument'
480
486
  require_relative 'rubocop/cop/style/exponential_notation'
487
+ require_relative 'rubocop/cop/style/file_read'
488
+ require_relative 'rubocop/cop/style/file_write'
481
489
  require_relative 'rubocop/cop/style/float_division'
482
490
  require_relative 'rubocop/cop/style/for'
483
491
  require_relative 'rubocop/cop/style/format_string'
@@ -510,10 +518,12 @@ require_relative 'rubocop/cop/style/keyword_parameters_order'
510
518
  require_relative 'rubocop/cop/style/lambda'
511
519
  require_relative 'rubocop/cop/style/lambda_call'
512
520
  require_relative 'rubocop/cop/style/line_end_concatenation'
521
+ require_relative 'rubocop/cop/style/map_to_hash'
513
522
  require_relative 'rubocop/cop/style/method_call_without_args_parentheses'
514
523
  require_relative 'rubocop/cop/style/method_call_with_args_parentheses'
515
524
  require_relative 'rubocop/cop/style/multiline_in_pattern_then'
516
525
  require_relative 'rubocop/cop/style/numbered_parameters'
526
+ require_relative 'rubocop/cop/style/open_struct_use'
517
527
  require_relative 'rubocop/cop/style/redundant_assignment'
518
528
  require_relative 'rubocop/cop/style/redundant_fetch_block'
519
529
  require_relative 'rubocop/cop/style/redundant_file_extension_in_require'
@@ -701,6 +711,7 @@ require_relative 'rubocop/cli/command/auto_genenerate_config'
701
711
  require_relative 'rubocop/cli/command/execute_runner'
702
712
  require_relative 'rubocop/cli/command/init_dotfile'
703
713
  require_relative 'rubocop/cli/command/show_cops'
714
+ require_relative 'rubocop/cli/command/show_docs_url'
704
715
  require_relative 'rubocop/cli/command/suggest_extensions'
705
716
  require_relative 'rubocop/cli/command/version'
706
717
  require_relative 'rubocop/config_regeneration'