rubocop 0.71.0 → 0.72.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (96) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +4 -8
  3. data/config/default.yml +42 -484
  4. data/lib/rubocop.rb +5 -53
  5. data/lib/rubocop/ast/builder.rb +2 -0
  6. data/lib/rubocop/ast/node.rb +1 -1
  7. data/lib/rubocop/ast/node/float_node.rb +12 -0
  8. data/lib/rubocop/ast/node/int_node.rb +12 -0
  9. data/lib/rubocop/ast/node/mixin/numeric_node.rb +21 -0
  10. data/lib/rubocop/ast/node/resbody_node.rb +1 -6
  11. data/lib/rubocop/cached_data.rb +1 -1
  12. data/lib/rubocop/config.rb +34 -5
  13. data/lib/rubocop/config_loader.rb +2 -6
  14. data/lib/rubocop/config_loader_resolver.rb +0 -14
  15. data/lib/rubocop/cop/cop.rb +0 -4
  16. data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +55 -0
  17. data/lib/rubocop/cop/layout/class_structure.rb +1 -1
  18. data/lib/rubocop/cop/layout/indent_first_argument.rb +6 -2
  19. data/lib/rubocop/cop/layout/indent_first_parameter.rb +7 -3
  20. data/lib/rubocop/cop/layout/indent_heredoc.rb +0 -1
  21. data/lib/rubocop/cop/layout/indentation_consistency.rb +13 -12
  22. data/lib/rubocop/cop/layout/indentation_width.rb +8 -4
  23. data/lib/rubocop/cop/lint/number_conversion.rb +1 -1
  24. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +21 -20
  25. data/lib/rubocop/cop/style/commented_keyword.rb +1 -1
  26. data/lib/rubocop/cop/style/conditional_assignment.rb +2 -1
  27. data/lib/rubocop/cop/style/float_division.rb +94 -0
  28. data/lib/rubocop/cop/style/format_string.rb +7 -3
  29. data/lib/rubocop/cop/style/if_inside_else.rb +42 -0
  30. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +7 -1
  31. data/lib/rubocop/cop/style/safe_navigation.rb +1 -1
  32. data/lib/rubocop/cop/style/ternary_parentheses.rb +12 -2
  33. data/lib/rubocop/cop/style/word_array.rb +2 -2
  34. data/lib/rubocop/cop/style/zero_length_predicate.rb +1 -1
  35. data/lib/rubocop/options.rb +0 -2
  36. data/lib/rubocop/processed_source.rb +2 -1
  37. data/lib/rubocop/rspec/cop_helper.rb +0 -1
  38. data/lib/rubocop/rspec/shared_contexts.rb +0 -17
  39. data/lib/rubocop/rspec/support.rb +0 -1
  40. data/lib/rubocop/runner.rb +0 -17
  41. data/lib/rubocop/version.rb +1 -1
  42. data/lib/rubocop/yaml_duplication_checker.rb +8 -2
  43. metadata +8 -91
  44. data/lib/rubocop/cop/mixin/target_rails_version.rb +0 -16
  45. data/lib/rubocop/cop/rails/action_filter.rb +0 -117
  46. data/lib/rubocop/cop/rails/active_record_aliases.rb +0 -48
  47. data/lib/rubocop/cop/rails/active_record_override.rb +0 -82
  48. data/lib/rubocop/cop/rails/active_support_aliases.rb +0 -69
  49. data/lib/rubocop/cop/rails/application_job.rb +0 -40
  50. data/lib/rubocop/cop/rails/application_record.rb +0 -40
  51. data/lib/rubocop/cop/rails/assert_not.rb +0 -44
  52. data/lib/rubocop/cop/rails/belongs_to.rb +0 -102
  53. data/lib/rubocop/cop/rails/blank.rb +0 -164
  54. data/lib/rubocop/cop/rails/bulk_change_table.rb +0 -289
  55. data/lib/rubocop/cop/rails/create_table_with_timestamps.rb +0 -91
  56. data/lib/rubocop/cop/rails/date.rb +0 -161
  57. data/lib/rubocop/cop/rails/delegate.rb +0 -132
  58. data/lib/rubocop/cop/rails/delegate_allow_blank.rb +0 -37
  59. data/lib/rubocop/cop/rails/dynamic_find_by.rb +0 -91
  60. data/lib/rubocop/cop/rails/enum_uniqueness.rb +0 -45
  61. data/lib/rubocop/cop/rails/environment_comparison.rb +0 -68
  62. data/lib/rubocop/cop/rails/exit.rb +0 -67
  63. data/lib/rubocop/cop/rails/file_path.rb +0 -108
  64. data/lib/rubocop/cop/rails/find_by.rb +0 -55
  65. data/lib/rubocop/cop/rails/find_each.rb +0 -51
  66. data/lib/rubocop/cop/rails/has_and_belongs_to_many.rb +0 -25
  67. data/lib/rubocop/cop/rails/has_many_or_has_one_dependent.rb +0 -106
  68. data/lib/rubocop/cop/rails/http_positional_arguments.rb +0 -117
  69. data/lib/rubocop/cop/rails/http_status.rb +0 -179
  70. data/lib/rubocop/cop/rails/ignored_skip_action_filter_option.rb +0 -94
  71. data/lib/rubocop/cop/rails/inverse_of.rb +0 -246
  72. data/lib/rubocop/cop/rails/lexically_scoped_action_filter.rb +0 -175
  73. data/lib/rubocop/cop/rails/link_to_blank.rb +0 -98
  74. data/lib/rubocop/cop/rails/not_null_column.rb +0 -67
  75. data/lib/rubocop/cop/rails/output.rb +0 -49
  76. data/lib/rubocop/cop/rails/output_safety.rb +0 -99
  77. data/lib/rubocop/cop/rails/pluralization_grammar.rb +0 -107
  78. data/lib/rubocop/cop/rails/presence.rb +0 -124
  79. data/lib/rubocop/cop/rails/present.rb +0 -153
  80. data/lib/rubocop/cop/rails/read_write_attribute.rb +0 -74
  81. data/lib/rubocop/cop/rails/redundant_allow_nil.rb +0 -111
  82. data/lib/rubocop/cop/rails/redundant_receiver_in_with_options.rb +0 -136
  83. data/lib/rubocop/cop/rails/reflection_class_name.rb +0 -37
  84. data/lib/rubocop/cop/rails/refute_methods.rb +0 -76
  85. data/lib/rubocop/cop/rails/relative_date_constant.rb +0 -93
  86. data/lib/rubocop/cop/rails/request_referer.rb +0 -56
  87. data/lib/rubocop/cop/rails/reversible_migration.rb +0 -286
  88. data/lib/rubocop/cop/rails/safe_navigation.rb +0 -87
  89. data/lib/rubocop/cop/rails/save_bang.rb +0 -316
  90. data/lib/rubocop/cop/rails/scope_args.rb +0 -29
  91. data/lib/rubocop/cop/rails/skips_model_validations.rb +0 -87
  92. data/lib/rubocop/cop/rails/time_zone.rb +0 -238
  93. data/lib/rubocop/cop/rails/uniq_before_pluck.rb +0 -105
  94. data/lib/rubocop/cop/rails/unknown_env.rb +0 -63
  95. data/lib/rubocop/cop/rails/validation.rb +0 -109
  96. data/lib/rubocop/rspec/shared_examples.rb +0 -59
@@ -83,7 +83,7 @@ module RuboCop
83
83
 
84
84
  check_indentation(end_loc, node.body)
85
85
 
86
- return unless indentation_consistency_style == 'rails'
86
+ return unless indented_internal_methods_style?
87
87
 
88
88
  check_members(end_loc, [node.body])
89
89
  end
@@ -155,8 +155,8 @@ module RuboCop
155
155
 
156
156
  return unless members.any? && members.first.begin_type?
157
157
 
158
- if indentation_consistency_style == 'rails'
159
- check_members_for_rails_style(members)
158
+ if indentation_consistency_style == 'indented_internal_methods'
159
+ check_members_for_indented_internal_methods_style(members)
160
160
  else
161
161
  members.first.children.each do |member|
162
162
  next if member.send_type? && member.access_modifier?
@@ -176,7 +176,7 @@ module RuboCop
176
176
  end
177
177
  end
178
178
 
179
- def check_members_for_rails_style(members)
179
+ def check_members_for_indented_internal_methods_style(members)
180
180
  each_member(members) do |member, previous_modifier|
181
181
  check_indentation(previous_modifier, member,
182
182
  indentation_consistency_style)
@@ -195,6 +195,10 @@ module RuboCop
195
195
  end
196
196
  end
197
197
 
198
+ def indented_internal_methods_style?
199
+ indentation_consistency_style == 'indented_internal_methods'
200
+ end
201
+
198
202
  def indentation_consistency_style
199
203
  config.for_cop('Layout/IndentationConsistency')['EnforcedStyle']
200
204
  end
@@ -64,7 +64,7 @@ module RuboCop
64
64
 
65
65
  def date_time_object?(node)
66
66
  child = node
67
- while child.send_type?
67
+ while child&.send_type?
68
68
  return true if datetime? child
69
69
 
70
70
  child = child.children[0]
@@ -57,24 +57,20 @@ module RuboCop
57
57
  MSG = 'Use `%<preferred>s` instead of `%<bad>s`.'
58
58
 
59
59
  def on_resbody(node)
60
- exception_type, @exception_name = *node
61
- return unless exception_type || @exception_name
62
-
63
- @exception_name ||= exception_type.children.first
64
- return if @exception_name.const_type? ||
65
- variable_name == preferred_name
60
+ name = variable_name(node)
61
+ return unless name
62
+ return if preferred_name(name).to_sym == name
66
63
 
67
64
  add_offense(node, location: offense_range(node))
68
65
  end
69
66
 
70
67
  def autocorrect(node)
71
68
  lambda do |corrector|
72
- offending_name = node.exception_variable.children.first
69
+ offending_name = variable_name(node)
70
+ preferred_name = preferred_name(offending_name)
73
71
  corrector.replace(offense_range(node), preferred_name)
74
72
 
75
- return unless node.body
76
-
77
- node.body.each_descendant(:lvar) do |var|
73
+ node.body&.each_descendant(:lvar) do |var|
78
74
  next unless var.children.first == offending_name
79
75
 
80
76
  corrector.replace(var.loc.expression, preferred_name)
@@ -89,21 +85,26 @@ module RuboCop
89
85
  variable.loc.expression
90
86
  end
91
87
 
92
- def preferred_name
93
- name = cop_config.fetch('PreferredName', 'e')
94
- variable_name.to_s.start_with?('_') ? "_#{name}" : name
88
+ def preferred_name(variable_name)
89
+ preferred_name = cop_config.fetch('PreferredName', 'e')
90
+ if variable_name.to_s.start_with?('_')
91
+ "_#{preferred_name}"
92
+ else
93
+ preferred_name
94
+ end
95
95
  end
96
96
 
97
- def variable_name
98
- location.source
99
- end
97
+ def variable_name(node)
98
+ asgn_node = node.exception_variable
99
+ return unless asgn_node
100
100
 
101
- def location
102
- @exception_name.loc.expression
101
+ asgn_node.children.last
103
102
  end
104
103
 
105
- def message(_node = nil)
106
- format(MSG, preferred: preferred_name, bad: variable_name)
104
+ def message(node)
105
+ offending_name = variable_name(node)
106
+ preferred_name = preferred_name(offending_name)
107
+ format(MSG, preferred: preferred_name, bad: offending_name)
107
108
  end
108
109
  end
109
110
  end
@@ -6,7 +6,7 @@ module RuboCop
6
6
  # This cop checks for comments put on the same line as some keywords.
7
7
  # These keywords are: `begin`, `class`, `def`, `end`, `module`.
8
8
  #
9
- # Note that some comments (`:nodoc:`, `:yields:, and `rubocop:disable`)
9
+ # Note that some comments (`:nodoc:`, `:yields:`, and `rubocop:disable`)
10
10
  # are allowed.
11
11
  #
12
12
  # @example
@@ -596,7 +596,8 @@ module RuboCop
596
596
 
597
597
  remove_whitespace_in_branches(corrector, branch, condition, column)
598
598
 
599
- branch_else = branch.parent.loc.else
599
+ return unless (branch_else = branch.parent.loc.else)
600
+
600
601
  corrector.remove_preceding(branch_else, branch_else.column - column)
601
602
  end
602
603
  end
@@ -0,0 +1,94 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Style
6
+ # This cop checks for division with integers coerced to floats.
7
+ # It is recommended to either always use `fdiv` or coerce one side only.
8
+ # This cop also provides other options for code consistency.
9
+ #
10
+ # @example EnforcedStyle: single_coerce (default)
11
+ # # bad
12
+ # a.to_f / b.to_f
13
+ #
14
+ # # good
15
+ # a.to_f / b
16
+ # a / b.to_f
17
+ #
18
+ # @example EnforcedStyle: left_coerce
19
+ # # bad
20
+ # a / b.to_f
21
+ # a.to_f / b.to_f
22
+ #
23
+ # # good
24
+ # a.to_f / b
25
+ #
26
+ # @example EnforcedStyle: right_coerce
27
+ # # bad
28
+ # a.to_f / b
29
+ # a.to_f / b.to_f
30
+ #
31
+ # # good
32
+ # a / b.to_f
33
+ #
34
+ # @example EnforcedStyle: fdiv
35
+ # # bad
36
+ # a / b.to_f
37
+ # a.to_f / b
38
+ # a.to_f / b.to_f
39
+ #
40
+ # # good
41
+ # a.fdiv(b)
42
+ class FloatDivision < Cop
43
+ include ConfigurableEnforcedStyle
44
+
45
+ def_node_matcher :right_coerce?, <<-PATTERN
46
+ (send _ :/ (send _ :to_f))
47
+ PATTERN
48
+ def_node_matcher :left_coerce?, <<-PATTERN
49
+ (send (send _ :to_f) :/ _)
50
+ PATTERN
51
+ def_node_matcher :both_coerce?, <<-PATTERN
52
+ (send (send _ :to_f) :/ (send _ :to_f))
53
+ PATTERN
54
+ def_node_matcher :any_coerce?, <<-PATTERN
55
+ {(send _ :/ (send _ :to_f)) (send (send _ :to_f) :/ _)}
56
+ PATTERN
57
+
58
+ def on_send(node)
59
+ add_offense(node) if offense_condition?(node)
60
+ end
61
+
62
+ private
63
+
64
+ def offense_condition?(node)
65
+ case style
66
+ when :left_coerce
67
+ right_coerce?(node)
68
+ when :right_coerce
69
+ left_coerce?(node)
70
+ when :single_coerce
71
+ both_coerce?(node)
72
+ when :fdiv
73
+ any_coerce?(node)
74
+ else
75
+ false
76
+ end
77
+ end
78
+
79
+ def message(_node)
80
+ case style
81
+ when :left_coerce
82
+ 'Prefer using `.to_f` on the left side.'
83
+ when :right_coerce
84
+ 'Prefer using `.to_f` on the right side.'
85
+ when :single_coerce
86
+ 'Prefer using `.to_f` on one side only.'
87
+ when :fdiv
88
+ 'Prefer using `fdiv` for float divisions.'
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
@@ -48,6 +48,10 @@ module RuboCop
48
48
  }
49
49
  PATTERN
50
50
 
51
+ def_node_matcher :variable_argument?, <<-PATTERN
52
+ (send {str dstr} :% {send_type? lvar_type?})
53
+ PATTERN
54
+
51
55
  def on_send(node)
52
56
  formatter(node) do |selector|
53
57
  detected_style = selector == :% ? :percent : selector
@@ -70,10 +74,10 @@ module RuboCop
70
74
  end
71
75
 
72
76
  def autocorrect(node)
73
- lambda do |corrector|
74
- detected_method = node.method_name
77
+ return if variable_argument?(node)
75
78
 
76
- case detected_method
79
+ lambda do |corrector|
80
+ case node.method_name
77
81
  when :%
78
82
  autocorrect_from_percent(corrector, node)
79
83
  when :format, :sprintf
@@ -27,6 +27,37 @@ module RuboCop
27
27
  # else
28
28
  # action_c
29
29
  # end
30
+ #
31
+ # @example AllowIfModifier: false (default)
32
+ # # bad
33
+ # if condition_a
34
+ # action_a
35
+ # else
36
+ # action_b if condition_b
37
+ # end
38
+ #
39
+ # # good
40
+ # if condition_a
41
+ # action_a
42
+ # elsif condition_b
43
+ # action_b
44
+ # end
45
+ #
46
+ # @example AllowIfModifier: true
47
+ # # good
48
+ # if condition_a
49
+ # action_a
50
+ # else
51
+ # action_b if condition_b
52
+ # end
53
+ #
54
+ # # good
55
+ # if condition_a
56
+ # action_a
57
+ # elsif condition_b
58
+ # action_b
59
+ # end
60
+ #
30
61
  class IfInsideElse < Cop
31
62
  MSG = 'Convert `if` nested inside `else` to `elsif`.'
32
63
 
@@ -36,9 +67,20 @@ module RuboCop
36
67
  else_branch = node.else_branch
37
68
 
38
69
  return unless else_branch&.if_type? && else_branch&.if?
70
+ return if allow_if_modifier_in_else_branch?(else_branch)
39
71
 
40
72
  add_offense(else_branch, location: :keyword)
41
73
  end
74
+
75
+ private
76
+
77
+ def allow_if_modifier_in_else_branch?(else_branch)
78
+ allow_if_modifier? && else_branch&.modifier_form?
79
+ end
80
+
81
+ def allow_if_modifier?
82
+ cop_config['AllowIfModifier']
83
+ end
42
84
  end
43
85
  end
44
86
  end
@@ -348,7 +348,8 @@ module RuboCop
348
348
  end
349
349
 
350
350
  def ambigious_literal?(node)
351
- splat?(node) || ternary_if?(node) || regexp_slash_literal?(node)
351
+ splat?(node) || ternary_if?(node) || regexp_slash_literal?(node) ||
352
+ unary_literal?(node)
352
353
  end
353
354
 
354
355
  def splat?(node)
@@ -371,6 +372,11 @@ module RuboCop
371
372
  node.regexp_type? && node.loc.begin.source == '/'
372
373
  end
373
374
 
375
+ def unary_literal?(node)
376
+ node.numeric_type? && node.sign? ||
377
+ node.parent&.send_type? && node.parent&.unary_operation?
378
+ end
379
+
374
380
  def assigned_before?(node, target)
375
381
  node.assignment? &&
376
382
  node.loc.operator.begin < target.loc.begin
@@ -224,7 +224,7 @@ module RuboCop
224
224
  end
225
225
 
226
226
  def method_called?(send_node)
227
- send_node.parent&.send_type?
227
+ send_node&.parent&.send_type?
228
228
  end
229
229
 
230
230
  def begin_range(node, method_call)
@@ -108,7 +108,7 @@ module RuboCop
108
108
  end
109
109
 
110
110
  def non_complex_send?(node)
111
- return false unless node.send_type?
111
+ return false unless node.call_type?
112
112
 
113
113
  !node.operator_method? || node.method?(:[])
114
114
  end
@@ -149,7 +149,8 @@ module RuboCop
149
149
 
150
150
  def unsafe_autocorrect?(condition)
151
151
  condition.children.any? do |child|
152
- unparenthesized_method_call?(child)
152
+ unparenthesized_method_call?(child) ||
153
+ below_ternary_precedence?(child)
153
154
  end
154
155
  end
155
156
 
@@ -157,6 +158,15 @@ module RuboCop
157
158
  method_name(child) =~ /^[a-z]/i && !child.parenthesized?
158
159
  end
159
160
 
161
+ def below_ternary_precedence?(child)
162
+ # Handle English "or", e.g. 'foo or bar ? a : b'
163
+ (child.or_type? && child.semantic_operator?) ||
164
+ # Handle English "and", e.g. 'foo and bar ? a : b'
165
+ (child.and_type? && child.semantic_operator?) ||
166
+ # Handle English "not", e.g. 'not foo ? a : b'
167
+ (child.send_type? && child.prefix_not?)
168
+ end
169
+
160
170
  def_node_matcher :method_name, <<-PATTERN
161
171
  {($:defined? (send nil? _) ...)
162
172
  (send {_ nil?} $_ _ ...)}
@@ -71,8 +71,8 @@ module RuboCop
71
71
 
72
72
  def complex_content?(strings)
73
73
  strings.any? do |s|
74
- string = s.str_content
75
- !string.dup.force_encoding(::Encoding::UTF_8).valid_encoding? ||
74
+ string = s.str_content.dup.force_encoding(::Encoding::UTF_8)
75
+ !string.valid_encoding? ||
76
76
  string !~ word_regex || string =~ / /
77
77
  end
78
78
  end
@@ -7,7 +7,7 @@ module RuboCop
7
7
  # by a predicate method, such as receiver.length == 0,
8
8
  # receiver.length > 0, receiver.length != 0,
9
9
  # receiver.length < 1 and receiver.size == 0 that can be
10
- # replaced by receiver.empty? and !receiver.empty.
10
+ # replaced by receiver.empty? and !receiver.empty?.
11
11
  #
12
12
  # @example
13
13
  # # bad
@@ -159,7 +159,6 @@ module RuboCop
159
159
  option(opts, '-D', '--[no-]display-cop-names')
160
160
  option(opts, '-E', '--extra-details')
161
161
  option(opts, '-S', '--display-style-guide')
162
- option(opts, '-R', '--rails')
163
162
  option(opts, '-a', '--auto-correct')
164
163
  option(opts, '--ignore-disable-comments')
165
164
 
@@ -429,7 +428,6 @@ module RuboCop
429
428
  'Default is true.'],
430
429
  display_style_guide: 'Display style guide URLs in offense messages.',
431
430
  extra_details: 'Display extra details in offense messages.',
432
- rails: 'Run extra Rails cops.',
433
431
  lint: 'Run only lint cops.',
434
432
  safe: 'Run only safe cops.',
435
433
  list_target_files: 'List all files RuboCop will inspect.',
@@ -187,7 +187,8 @@ module RuboCop
187
187
  require 'parser/ruby27'
188
188
  Parser::Ruby27
189
189
  else
190
- raise ArgumentError, "Unknown Ruby version: #{ruby_version.inspect}"
190
+ raise ArgumentError,
191
+ "RuboCop found unknown Ruby version: #{ruby_version.inspect}"
191
192
  end
192
193
  end
193
194
  # rubocop:enable Metrics/MethodLength
@@ -7,7 +7,6 @@ module CopHelper
7
7
  extend RSpec::SharedContext
8
8
 
9
9
  let(:ruby_version) { 2.3 }
10
- let(:enabled_rails) { false }
11
10
  let(:rails_version) { false }
12
11
 
13
12
  def inspect_source_file(source)
@@ -47,7 +47,6 @@ RSpec.shared_context 'config', :config do
47
47
  end
48
48
 
49
49
  hash = { 'AllCops' => { 'TargetRubyVersion' => ruby_version } }
50
- hash['Rails'] = { 'Enabled' => true } if enabled_rails
51
50
  hash['AllCops']['TargetRailsVersion'] = rails_version if rails_version
52
51
  if respond_to?(:cop_config)
53
52
  cop_name = described_class.cop_name
@@ -77,19 +76,3 @@ end
77
76
  RSpec.shared_context 'ruby 2.6', :ruby26 do
78
77
  let(:ruby_version) { 2.6 }
79
78
  end
80
-
81
- RSpec.shared_context 'with Rails', :enabled_rails do
82
- let(:enabled_rails) { true }
83
- end
84
-
85
- RSpec.shared_context 'with Rails 3', :rails3 do
86
- let(:rails_version) { 3.0 }
87
- end
88
-
89
- RSpec.shared_context 'with Rails 4', :rails4 do
90
- let(:rails_version) { 4.0 }
91
- end
92
-
93
- RSpec.shared_context 'with Rails 5', :rails5 do
94
- let(:rails_version) { 5.0 }
95
- end