rubocop 0.63.1 → 0.64.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 (53) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +10 -1
  4. data/lib/rubocop.rb +1 -0
  5. data/lib/rubocop/cop/generator/configuration_injector.rb +5 -4
  6. data/lib/rubocop/cop/layout/align_parameters.rb +6 -1
  7. data/lib/rubocop/cop/layout/closing_heredoc_indentation.rb +0 -12
  8. data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +9 -7
  9. data/lib/rubocop/cop/layout/dot_position.rb +12 -5
  10. data/lib/rubocop/cop/layout/empty_lines_around_arguments.rb +1 -0
  11. data/lib/rubocop/cop/layout/first_method_argument_line_break.rb +1 -0
  12. data/lib/rubocop/cop/layout/first_parameter_indentation.rb +1 -0
  13. data/lib/rubocop/cop/layout/indent_array.rb +1 -0
  14. data/lib/rubocop/cop/layout/indent_hash.rb +1 -0
  15. data/lib/rubocop/cop/layout/indentation_width.rb +1 -0
  16. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +1 -3
  17. data/lib/rubocop/cop/layout/space_before_first_arg.rb +1 -0
  18. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +1 -0
  19. data/lib/rubocop/cop/lint/disjunctive_assignment_in_constructor.rb +1 -1
  20. data/lib/rubocop/cop/lint/each_with_object_argument.rb +4 -1
  21. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +2 -1
  22. data/lib/rubocop/cop/lint/require_parentheses.rb +1 -0
  23. data/lib/rubocop/cop/mixin/check_assignment.rb +1 -1
  24. data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +3 -6
  25. data/lib/rubocop/cop/mixin/trailing_comma.rb +9 -3
  26. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +10 -7
  27. data/lib/rubocop/cop/performance/chain_array_allocation.rb +3 -2
  28. data/lib/rubocop/cop/rails/active_record_aliases.rb +2 -0
  29. data/lib/rubocop/cop/rails/belongs_to.rb +1 -1
  30. data/lib/rubocop/cop/rails/date.rb +1 -0
  31. data/lib/rubocop/cop/rails/dynamic_find_by.rb +1 -0
  32. data/lib/rubocop/cop/rails/find_by.rb +2 -1
  33. data/lib/rubocop/cop/rails/link_to_blank.rb +3 -1
  34. data/lib/rubocop/cop/rails/reflection_class_name.rb +38 -0
  35. data/lib/rubocop/cop/rails/save_bang.rb +1 -0
  36. data/lib/rubocop/cop/rails/skips_model_validations.rb +1 -0
  37. data/lib/rubocop/cop/rails/validation.rb +9 -4
  38. data/lib/rubocop/cop/style/braces_around_hash_parameters.rb +1 -0
  39. data/lib/rubocop/cop/style/commented_keyword.rb +3 -3
  40. data/lib/rubocop/cop/style/empty_literal.rb +8 -5
  41. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +32 -6
  42. data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +1 -0
  43. data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +2 -1
  44. data/lib/rubocop/cop/style/one_line_conditional.rb +2 -0
  45. data/lib/rubocop/cop/style/preferred_hash_methods.rb +1 -0
  46. data/lib/rubocop/cop/style/send.rb +2 -1
  47. data/lib/rubocop/cop/style/string_methods.rb +1 -0
  48. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +1 -0
  49. data/lib/rubocop/cop/style/unneeded_condition.rb +3 -2
  50. data/lib/rubocop/cop/style/yoda_condition.rb +0 -5
  51. data/lib/rubocop/platform.rb +1 -1
  52. data/lib/rubocop/version.rb +1 -1
  53. metadata +3 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 403ba108281ac77da6c733ad24b88350e4b4a3055ad36b6059d7784cbf4df56e
4
- data.tar.gz: 86ebf007930c2de6e2f5eddbd0a6fba6e99ce9a7645f6407fdd4554a4e3c632c
3
+ metadata.gz: 6c744e17f8f6d38daae30955f4198b9d34856917a7f3ec60b143b2cec3047aff
4
+ data.tar.gz: 9eb2f51c58eda0558444895d38fa246d21b6a055aadc4d901a320dca2f4ce4eb
5
5
  SHA512:
6
- metadata.gz: 65c260a9df4e731b52ed42e5412d100e71199d5b75e6dac98adaf097020b351019c3fabedd99f2c34465d414eba0439680aeb7799ece4321c63918b4ac2e46e9
7
- data.tar.gz: 5bfe411917f9d371b3ce33464297b5aa7840959dccf1275553545601af6b5228a7e770e3993663b98d5880f91f18dfdb94cf55cfa697af923e63c3b9fb3bcd8f
6
+ metadata.gz: c2d2beac27d36a4ef480f55c4125ddab230e1b208b45c90f59b3435f83eaa87f969ef0228bd959a7c25c3a91763bb941a9a778da5f6c9c925f0c9c698a631ef6
7
+ data.tar.gz: 597c8b8c1454fd8e3734ed545a5d148353d1b8860232ac3eed9b633c15f17fb2399f12874c7ec13191bdcd57709ff12653877080982f900426ff2452c6421a41
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 locking in your `Gemfile`:
54
54
 
55
55
  ```rb
56
- gem 'rubocop', '~> 0.63.1', require: false
56
+ gem 'rubocop', '~> 0.64.0', require: false
57
57
  ```
58
58
 
59
59
  ## Quickstart
@@ -2493,6 +2493,11 @@ Rails/RedundantReceiverInWithOptions:
2493
2493
  Enabled: true
2494
2494
  VersionAdded: '0.52'
2495
2495
 
2496
+ Rails/ReflectionClassName:
2497
+ Description: 'Use a string for `class_name` option value in the definition of a reflection.'
2498
+ Enabled: true
2499
+ VersionAdded: '0.64'
2500
+
2496
2501
  Rails/RefuteMethods:
2497
2502
  Description: 'Use `assert_not` methods instead of `refute` methods.'
2498
2503
  Enabled: true
@@ -3374,7 +3379,9 @@ Style/LineEndConcatenation:
3374
3379
  Use \ instead of + or << to concatenate two string literals at
3375
3380
  line end.
3376
3381
  Enabled: true
3382
+ SafeAutoCorrect: false
3377
3383
  VersionAdded: '0.18'
3384
+ VersionChanged: '0.64'
3378
3385
 
3379
3386
  Style/MethodCallWithArgsParentheses:
3380
3387
  Description: 'Use parentheses for method calls with arguments.'
@@ -3386,6 +3393,7 @@ Style/MethodCallWithArgsParentheses:
3386
3393
  IgnoredMethods: []
3387
3394
  AllowParenthesesInMultilineCall: false
3388
3395
  AllowParenthesesInChaining: false
3396
+ AllowParenthesesInCamelCaseMethod: false
3389
3397
  EnforcedStyle: require_parentheses
3390
3398
  SupportedStyles:
3391
3399
  - require_parentheses
@@ -4088,8 +4096,9 @@ Style/SymbolLiteral:
4088
4096
  Style/SymbolProc:
4089
4097
  Description: 'Use symbols as procs instead of blocks when possible.'
4090
4098
  Enabled: true
4099
+ SafeAutoCorrect: false
4091
4100
  VersionAdded: '0.26'
4092
- VersionChanged: '0.40'
4101
+ VersionChanged: '0.64'
4093
4102
  # A list of method names to be ignored by the check.
4094
4103
  # The names should be fairly unique, otherwise you'll end up ignoring lots of code.
4095
4104
  IgnoredMethods:
@@ -592,6 +592,7 @@ require_relative 'rubocop/cop/rails/presence'
592
592
  require_relative 'rubocop/cop/rails/present'
593
593
  require_relative 'rubocop/cop/rails/read_write_attribute'
594
594
  require_relative 'rubocop/cop/rails/redundant_receiver_in_with_options'
595
+ require_relative 'rubocop/cop/rails/reflection_class_name'
595
596
  require_relative 'rubocop/cop/rails/refute_methods'
596
597
  require_relative 'rubocop/cop/rails/relative_date_constant'
597
598
  require_relative 'rubocop/cop/rails/request_referer'
@@ -45,14 +45,15 @@ module RuboCop
45
45
 
46
46
  def find_target_line
47
47
  configuration_entries.find.with_index do |line, index|
48
- next if comment?(line)
48
+ next unless cop_name_line?(line)
49
49
 
50
- break index if badge.to_s < line
50
+ return index if badge.to_s < line
51
51
  end
52
+ configuration_entries.size - 1
52
53
  end
53
54
 
54
- def comment?(yaml)
55
- yaml =~ /^[\s#]/
55
+ def cop_name_line?(yaml)
56
+ yaml !~ /^[\s#]/
56
57
  end
57
58
  end
58
59
  end
@@ -42,6 +42,7 @@ module RuboCop
42
42
 
43
43
  check_alignment(node.arguments, base_column(node, node.arguments))
44
44
  end
45
+ alias on_csend on_send
45
46
  alias on_def on_send
46
47
  alias on_defs on_send
47
48
 
@@ -52,7 +53,11 @@ module RuboCop
52
53
  private
53
54
 
54
55
  def message(node)
55
- type = node && node.parent.send_type? ? 'call' : 'definition'
56
+ type = if node && (node.parent.send_type? || node.parent.csend_type?)
57
+ 'call'
58
+ else
59
+ 'definition'
60
+ end
56
61
  msg = fixed_indentation? ? FIXED_INDENT_MSG : ALIGN_PARAMS_MSG
57
62
 
58
63
  format(msg, type: type)
@@ -74,10 +74,6 @@ module RuboCop
74
74
  indent_level(heredoc_opening(node))
75
75
  end
76
76
 
77
- def empty_heredoc?(node)
78
- node.loc.heredoc_body.source.empty? || !contents_indentation(node)
79
- end
80
-
81
77
  def argument_indentation_correct?(node)
82
78
  return unless node.argument? || node.chained?
83
79
 
@@ -86,14 +82,6 @@ module RuboCop
86
82
  ) == closing_indentation(node)
87
83
  end
88
84
 
89
- def contents_indentation(node)
90
- source_lines = node.loc.heredoc_body.source.split("\n")
91
-
92
- source_lines.reject(&:empty?).map do |line|
93
- indent_level(line)
94
- end.min
95
- end
96
-
97
85
  def closing_indentation(node)
98
86
  indent_level(heredoc_closing(node))
99
87
  end
@@ -78,6 +78,7 @@ module RuboCop
78
78
  def on_send(node)
79
79
  check(node, node.arguments)
80
80
  end
81
+ alias on_csend on_send
81
82
 
82
83
  def on_begin(node)
83
84
  check(node, node.children)
@@ -142,15 +143,16 @@ module RuboCop
142
143
  end
143
144
 
144
145
  def expected_column(left_paren, elements)
145
- if !line_break_after_left_paren?(left_paren, elements) &&
146
- all_elements_aligned?(elements)
147
- left_paren.column
148
- else
146
+ if line_break_after_left_paren?(left_paren, elements)
149
147
  source_indent = processed_source
150
- .line_indentation(last_argument_line(elements))
148
+ .line_indentation(first_argument_line(elements))
151
149
  new_indent = source_indent - indentation_width
152
150
 
153
151
  new_indent < 0 ? 0 : new_indent
152
+ elsif all_elements_aligned?(elements)
153
+ left_paren.column
154
+ else
155
+ processed_source.line_indentation(first_argument_line(elements))
154
156
  end
155
157
  end
156
158
 
@@ -161,9 +163,9 @@ module RuboCop
161
163
  .count == 1
162
164
  end
163
165
 
164
- def last_argument_line(elements)
166
+ def first_argument_line(elements)
165
167
  elements
166
- .last
168
+ .first
167
169
  .loc
168
170
  .first_line
169
171
  end
@@ -26,7 +26,7 @@ module RuboCop
26
26
  include ConfigurableEnforcedStyle
27
27
 
28
28
  def on_send(node)
29
- return unless node.dot?
29
+ return unless node.dot? || ampersand_dot?(node)
30
30
 
31
31
  if proper_dot_position?(node)
32
32
  correct_style_detected
@@ -34,23 +34,26 @@ module RuboCop
34
34
  add_offense(node, location: :dot) { opposite_style_detected }
35
35
  end
36
36
  end
37
+ alias on_csend on_send
37
38
 
38
39
  def autocorrect(node)
39
40
  lambda do |corrector|
41
+ dot = node.loc.dot.source
40
42
  corrector.remove(node.loc.dot)
41
43
  case style
42
44
  when :leading
43
- corrector.insert_before(selector_range(node), '.')
45
+ corrector.insert_before(selector_range(node), dot)
44
46
  when :trailing
45
- corrector.insert_after(node.receiver.source_range, '.')
47
+ corrector.insert_after(node.receiver.source_range, dot)
46
48
  end
47
49
  end
48
50
  end
49
51
 
50
52
  private
51
53
 
52
- def message(_node)
53
- 'Place the . on the ' +
54
+ def message(node)
55
+ dot = node.loc.dot.source
56
+ "Place the #{dot} on the " +
54
57
  case style
55
58
  when :leading
56
59
  'next line, together with the method name.'
@@ -92,6 +95,10 @@ module RuboCop
92
95
  # l.(1) has no selector, so we use the opening parenthesis instead
93
96
  node.loc.selector || node.loc.begin
94
97
  end
98
+
99
+ def ampersand_dot?(node)
100
+ node.loc.respond_to?(:dot) && node.loc.dot && node.loc.dot.is?('&.')
101
+ end
95
102
  end
96
103
  end
97
104
  end
@@ -48,6 +48,7 @@ module RuboCop
48
48
 
49
49
  extra_lines(node) { |range| add_offense(node, location: range) }
50
50
  end
51
+ alias on_csend on_send
51
52
 
52
53
  def autocorrect(node)
53
54
  lambda do |corrector|
@@ -43,6 +43,7 @@ module RuboCop
43
43
 
44
44
  check_method_line_break(node, args)
45
45
  end
46
+ alias on_csend on_send
46
47
 
47
48
  def autocorrect(node)
48
49
  EmptyLineCorrector.insert_before(node)
@@ -154,6 +154,7 @@ module RuboCop
154
154
 
155
155
  check_alignment([node.first_argument], indent)
156
156
  end
157
+ alias on_csend on_send
157
158
 
158
159
  def autocorrect(node)
159
160
  AlignmentCorrector.correct(processed_source, node, column_delta)
@@ -96,6 +96,7 @@ module RuboCop
96
96
  check(array_node, left_parenthesis)
97
97
  end
98
98
  end
99
+ alias on_csend on_send
99
100
 
100
101
  def autocorrect(node)
101
102
  AlignmentCorrector.correct(processed_source, node, @column_delta)
@@ -94,6 +94,7 @@ module RuboCop
94
94
  check(hash_node, left_parenthesis)
95
95
  end
96
96
  end
97
+ alias on_csend on_send
97
98
 
98
99
  def autocorrect(node)
99
100
  AlignmentCorrector.correct(processed_source, node, @column_delta)
@@ -119,6 +119,7 @@ module RuboCop
119
119
  check_indentation(base.source_range, body)
120
120
  ignore_node(node.first_argument)
121
121
  end
122
+ alias on_csend on_send
122
123
 
123
124
  def on_def(node)
124
125
  return if ignored_node?(node)
@@ -30,7 +30,6 @@ module RuboCop
30
30
  ANCESTOR_TYPES = %i[kwbegin def defs class module].freeze
31
31
  RUBY_2_5_ANCESTOR_TYPES = (ANCESTOR_TYPES + %i[block]).freeze
32
32
  ANCESTOR_TYPES_WITH_ACCESS_MODIFIERS = %i[def defs].freeze
33
- ASSIGNMENT_TYPES = %i[lvasgn].freeze
34
33
 
35
34
  def on_resbody(node)
36
35
  check(node) unless modifier?(node)
@@ -141,8 +140,7 @@ module RuboCop
141
140
  def assignment_node(node)
142
141
  assignment_node = node.ancestors.first
143
142
  return nil unless
144
- assignment_node &&
145
- ASSIGNMENT_TYPES.include?(assignment_node.type)
143
+ assignment_node && assignment_node.assignment?
146
144
 
147
145
  assignment_node
148
146
  end
@@ -40,6 +40,7 @@ module RuboCop
40
40
 
41
41
  add_offense(space, location: space) if space.length != 1
42
42
  end
43
+ alias on_csend on_send
43
44
 
44
45
  def autocorrect(range)
45
46
  ->(corrector) { corrector.replace(range, ' ') }
@@ -37,6 +37,7 @@ module RuboCop
37
37
 
38
38
  add_offense(node)
39
39
  end
40
+ alias on_csend on_send
40
41
 
41
42
  private
42
43
 
@@ -31,13 +31,13 @@ module RuboCop
31
31
 
32
32
  private
33
33
 
34
+ # @param [DefNode] node a constructor definition
34
35
  def check(node)
35
36
  return unless node.method_name == :initialize
36
37
 
37
38
  check_body(node.body)
38
39
  end
39
40
 
40
- # @param [DefNode] node a constructor definition
41
41
  def check_body(body)
42
42
  return if body.nil?
43
43
 
@@ -24,7 +24,9 @@ module RuboCop
24
24
  class EachWithObjectArgument < Cop
25
25
  MSG = 'The argument to each_with_object can not be immutable.'.freeze
26
26
 
27
- def_node_matcher :each_with_object?, '(send _ :each_with_object $_)'
27
+ def_node_matcher :each_with_object?, <<-PATTERN
28
+ ({send csend} _ :each_with_object $_)
29
+ PATTERN
28
30
 
29
31
  def on_send(node)
30
32
  each_with_object?(node) do |arg|
@@ -33,6 +35,7 @@ module RuboCop
33
35
  add_offense(node)
34
36
  end
35
37
  end
38
+ alias on_csend on_send
36
39
  end
37
40
  end
38
41
  end
@@ -35,6 +35,7 @@ module RuboCop
35
35
 
36
36
  add_offense(nil, location: range)
37
37
  end
38
+ alias on_csend on_send
38
39
 
39
40
  private
40
41
 
@@ -50,7 +51,7 @@ module RuboCop
50
51
  # Escape question mark if any.
51
52
  method_regexp = Regexp.escape(node.method_name)
52
53
 
53
- match = without_receiver.match(/^\s*\.?\s*#{method_regexp}(\s+)\(/)
54
+ match = without_receiver.match(/^\s*&?\.?\s*#{method_regexp}(\s+)\(/)
54
55
  match ? match.captures[0].length : 0
55
56
  end
56
57
 
@@ -42,6 +42,7 @@ module RuboCop
42
42
  check_predicate(node.last_argument, node)
43
43
  end
44
44
  end
45
+ alias on_csend on_send
45
46
 
46
47
  private
47
48
 
@@ -31,7 +31,7 @@ module RuboCop
31
31
  _scope, _lhs, rhs = *node
32
32
  elsif node.op_asgn_type?
33
33
  _lhs, _op, rhs = *node
34
- elsif node.send_type?
34
+ elsif node.send_type? || node.csend_type?
35
35
  rhs = node.last_argument
36
36
  elsif node.assignment?
37
37
  _lhs, rhs = *node
@@ -54,12 +54,9 @@ module RuboCop
54
54
  end
55
55
 
56
56
  def variable_alignment?(whole_expression, rhs, end_alignment_style)
57
- case end_alignment_style
58
- when :variable
59
- !line_break_before_keyword?(whole_expression, rhs)
60
- when :start_of_line
61
- true
62
- end
57
+ return if end_alignment_style == :keyword
58
+
59
+ !line_break_before_keyword?(whole_expression, rhs)
63
60
  end
64
61
 
65
62
  def line_break_before_keyword?(whole_expression, rhs)
@@ -17,11 +17,13 @@ module RuboCop
17
17
  end
18
18
 
19
19
  def check(node, items, kind, begin_pos, end_pos)
20
- return if heredoc?(items.last)
21
-
22
20
  after_last_item = range_between(begin_pos, end_pos)
23
21
 
24
- comma_offset = after_last_item.source =~ /,/
22
+ # If there is any heredoc in items, then match the comma succeeding
23
+ # any whitespace (except newlines), otherwise allow for newlines
24
+ comma_regex = any_heredoc?(items) ? /\A[^\S\n]*,/ : /\A\s*,/
25
+ comma_offset = after_last_item.source =~ comma_regex &&
26
+ after_last_item.source.index(',')
25
27
 
26
28
  if comma_offset && !inside_comment?(after_last_item, comma_offset)
27
29
  check_comma(node, kind, after_last_item.begin_pos + comma_offset)
@@ -167,6 +169,10 @@ module RuboCop
167
169
  false
168
170
  end
169
171
 
172
+ def any_heredoc?(items)
173
+ items.any? { |item| heredoc?(item) }
174
+ end
175
+
170
176
  def heredoc?(node)
171
177
  return false unless node.is_a?(RuboCop::AST::Node)
172
178
  return true if node.loc.respond_to?(:heredoc_body)
@@ -132,9 +132,7 @@ module RuboCop
132
132
  variable = ivar_assign.children.first
133
133
  variable_name = variable.to_s.sub('@', '')
134
134
 
135
- return false unless valid_leading_underscore?(variable_name)
136
-
137
- variable_name.sub(/\A_/, '') == method_name.sub(/\A_/, '')
135
+ variable_name_candidates(method_name).include?(variable_name)
138
136
  end
139
137
 
140
138
  def message(variable)
@@ -152,14 +150,19 @@ module RuboCop
152
150
  style == :required ? "_#{suggestion}" : suggestion
153
151
  end
154
152
 
155
- def valid_leading_underscore?(variable_name)
153
+ def variable_name_candidates(method_name)
154
+ no_underscore = method_name.sub(/\A_/, '')
155
+ with_underscore = "_#{method_name}"
156
156
  case style
157
157
  when :required
158
- variable_name.start_with?('_')
158
+ [with_underscore,
159
+ method_name.start_with?('_') ? method_name : nil].compact
159
160
  when :disallowed
160
- !variable_name.start_with?('_')
161
+ [method_name, no_underscore]
162
+ when :optional
163
+ [method_name, with_underscore, no_underscore]
161
164
  else
162
- true
165
+ raise 'Unreachable'
163
166
  end
164
167
  end
165
168
  end
@@ -47,8 +47,9 @@ module RuboCop
47
47
  HAS_MUTATION_ALTERNATIVE = ':collect :compact :flatten :map :reject '\
48
48
  ':reverse :rotate :select :shuffle :sort '\
49
49
  ':uniq '.freeze
50
- MSG = 'Use `%<method>s...%<second_method>s!` instead of `%<method>s' \
51
- '...%<second_method>s`.'.freeze
50
+ MSG = 'Use unchained `%<method>s!` and `%<second_method>s!` '\
51
+ '(followed by `return array` if required) instead of chaining '\
52
+ '`%<method>s...%<second_method>s`.'.freeze
52
53
 
53
54
  def_node_matcher :flat_map_candidate?, <<-PATTERN
54
55
  {
@@ -32,6 +32,8 @@ module RuboCop
32
32
  end
33
33
  end
34
34
 
35
+ alias on_csend on_send
36
+
35
37
  def autocorrect(node)
36
38
  lambda do |corrector|
37
39
  corrector.replace(
@@ -19,7 +19,7 @@ module RuboCop
19
19
  # In the case that the developer is doing `required: false`, we
20
20
  # definitely want to autocorrect to `optional: true`.
21
21
  #
22
- # However, without knowing whether they've set overriden the default
22
+ # However, without knowing whether they've set overridden the default
23
23
  # value of `config.active_record.belongs_to_required_by_default`, we
24
24
  # can't say whether it's safe to remove `required: true` or whether we
25
25
  # should replace it with `optional: false` (or, similarly, remove a
@@ -79,6 +79,7 @@ module RuboCop
79
79
  add_offense(node, location: :selector,
80
80
  message: format(MSG_SEND, method: node.method_name))
81
81
  end
82
+ alias on_csend on_send
82
83
 
83
84
  private
84
85
 
@@ -42,6 +42,7 @@ module RuboCop
42
42
  message: format(MSG, static_name: static_name,
43
43
  method: node.method_name))
44
44
  end
45
+ alias on_csend on_send
45
46
 
46
47
  def autocorrect(node)
47
48
  keywords = column_keywords(node.method_name)
@@ -20,7 +20,7 @@ module RuboCop
20
20
  TARGET_SELECTORS = %i[first take].freeze
21
21
 
22
22
  def_node_matcher :where_first?, <<-PATTERN
23
- (send (send _ :where ...) {:first :take})
23
+ (send ({send csend} _ :where ...) {:first :take})
24
24
  PATTERN
25
25
 
26
26
  def on_send(node)
@@ -32,6 +32,7 @@ module RuboCop
32
32
  add_offense(node, location: range,
33
33
  message: format(MSG, method: node.method_name))
34
34
  end
35
+ alias on_csend on_send
35
36
 
36
37
  def autocorrect(node)
37
38
  # Don't autocorrect where(...).first, because it can return different
@@ -74,7 +74,9 @@ module RuboCop
74
74
  def add_rel(send_node, offence_node, corrector)
75
75
  quote_style = offence_node.children.last.source[0]
76
76
  new_rel_exp = ", rel: #{quote_style}noopener#{quote_style}"
77
- corrector.insert_after(send_node.loc.expression, new_rel_exp)
77
+ range = send_node.arguments.last.source_range
78
+
79
+ corrector.insert_after(range, new_rel_exp)
78
80
  end
79
81
 
80
82
  def contains_noopener?(str)
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Rails
6
+ # This cop checks if the value of the option `class_name`, in
7
+ # the definition of a reflection is a string.
8
+ #
9
+ # @example
10
+ # # bad
11
+ # has_many :accounts, class_name: Account
12
+ # has_many :accounts, class_name: Account.name
13
+ #
14
+ # # good
15
+ # has_many :accounts, class_name: 'Account'
16
+ class ReflectionClassName < Cop
17
+ MSG = 'Use a string has value for a class_name.'.freeze
18
+
19
+ def_node_matcher :association_with_options?, <<-PATTERN
20
+ (send nil? {:has_many :has_one :belongs_to} _ (hash $...))
21
+ PATTERN
22
+
23
+ def_node_search :reflection_class_name, <<-PATTERN
24
+ (pair (sym :class_name) !str)
25
+ PATTERN
26
+
27
+ def on_send(node)
28
+ return unless association_with_options?(node)
29
+
30
+ reflection_class_name = reflection_class_name(node).first
31
+ return unless reflection_class_name
32
+
33
+ add_offense(node, location: reflection_class_name.loc.expression)
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -146,6 +146,7 @@ module RuboCop
146
146
 
147
147
  add_offense_for_node(node)
148
148
  end
149
+ alias on_csend on_send
149
150
 
150
151
  def autocorrect(node)
151
152
  save_loc = node.loc.selector
@@ -67,6 +67,7 @@ module RuboCop
67
67
 
68
68
  add_offense(node, location: :selector)
69
69
  end
70
+ alias on_csend on_send
70
71
 
71
72
  private
72
73
 
@@ -57,6 +57,9 @@ module RuboCop
57
57
  end
58
58
 
59
59
  def autocorrect(node)
60
+ last_argument = node.arguments.last
61
+ return if !last_argument.literal? && !last_argument.splat_type?
62
+
60
63
  lambda do |corrector|
61
64
  corrector.replace(node.loc.selector, 'validates')
62
65
  correct_validate_type(corrector, node)
@@ -75,12 +78,14 @@ module RuboCop
75
78
  end
76
79
 
77
80
  def correct_validate_type(corrector, node)
78
- options = node.arguments.find { |arg| !arg.sym_type? }
81
+ last_argument = node.arguments.last
79
82
  validate_type = node.method_name.to_s.split('_')[1]
80
83
 
81
- if options
82
- corrector.replace(options.loc.expression,
83
- "#{validate_type}: #{braced_options(options)}")
84
+ if last_argument.hash_type?
85
+ corrector.replace(
86
+ last_argument.loc.expression,
87
+ "#{validate_type}: #{braced_options(last_argument)}"
88
+ )
84
89
  else
85
90
  corrector.insert_after(node.loc.expression,
86
91
  ", #{validate_type}: true")
@@ -53,6 +53,7 @@ module RuboCop
53
53
 
54
54
  check(node.last_argument, node.arguments)
55
55
  end
56
+ alias on_csend on_send
56
57
 
57
58
  # We let AutocorrectUnlessChangingAST#autocorrect work with the send
58
59
  # node, because that context is needed. When parsing the code to see if
@@ -6,8 +6,8 @@ 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 (such as `:nodoc:` and `rubocop:disable`) are
10
- # allowed.
9
+ # Note that some comments (`:nodoc:`, `:yields:, and `rubocop:disable`)
10
+ # are allowed.
11
11
  #
12
12
  # @example
13
13
  # # bad
@@ -59,7 +59,7 @@ module RuboCop
59
59
  private
60
60
 
61
61
  KEYWORDS = %w[begin class def end module].freeze
62
- ALLOWED_COMMENTS = %w[:nodoc: rubocop:disable].freeze
62
+ ALLOWED_COMMENTS = %w[:nodoc: :yields: rubocop:disable].freeze
63
63
 
64
64
  def offensive?(line)
65
65
  line = line.lstrip
@@ -67,10 +67,13 @@ module RuboCop
67
67
  end
68
68
 
69
69
  def first_argument_unparenthesized?(node)
70
- return false unless node.parent && node.parent.send_type?
70
+ parent = node.parent
71
+ unless parent && %i[send super zsuper].include?(parent.type)
72
+ return false
73
+ end
71
74
 
72
- _receiver, _method_name, *args = *node.parent
73
- node.object_id == args.first.object_id && !parentheses?(node.parent)
75
+ node.object_id == parent.arguments.first.object_id &&
76
+ !parentheses?(node.parent)
74
77
  end
75
78
 
76
79
  def replacement_range(node)
@@ -79,7 +82,7 @@ module RuboCop
79
82
  # `some_method {}` is not same as `some_method Hash.new`
80
83
  # because the braces are interpreted as a block. We will have
81
84
  # to rewrite the arguments to wrap them in parenthesis.
82
- _receiver, _method_name, *args = *node.parent
85
+ args = node.parent.arguments
83
86
 
84
87
  range_between(args[0].loc.expression.begin_pos - 1,
85
88
  args[-1].loc.expression.end_pos)
@@ -107,7 +110,7 @@ module RuboCop
107
110
  # `some_method {}` is not same as `some_method Hash.new`
108
111
  # because the braces are interpreted as a block. We will have
109
112
  # to rewrite the arguments to wrap them in parenthesis.
110
- _receiver, _method_name, *args = *node.parent
113
+ args = node.parent.arguments
111
114
  "(#{args[1..-1].map(&:source).unshift('{}').join(', ')})"
112
115
  else
113
116
  '{}'
@@ -10,7 +10,7 @@ module RuboCop
10
10
  # Additional methods can be added to the `IgnoredMethods` list. This
11
11
  # option is valid only in the default style.
12
12
  #
13
- # In the alternative style (omit_parentheses), there are two additional
13
+ # In the alternative style (omit_parentheses), there are three additional
14
14
  # options.
15
15
  #
16
16
  # 1. `AllowParenthesesInChaining` is `false` by default. Setting it to
@@ -21,6 +21,12 @@ module RuboCop
21
21
  # to `true` allows the presence of parentheses in multi-line method
22
22
  # calls.
23
23
  #
24
+ # 3. `AllowParenthesesInCamelCaseMethod` is `false` by default. This
25
+ # allows the presence of parentheses when calling a method whose name
26
+ # begins with a capital letter and which has no arguments. Setting it
27
+ # to `true` allows the presence of parentheses in such a method call
28
+ # even with arguments.
29
+ #
24
30
  # @example EnforcedStyle: require_parentheses (default)
25
31
  #
26
32
  #
@@ -106,6 +112,22 @@ module RuboCop
106
112
  #
107
113
  # # good
108
114
  # foo().bar 1
115
+ #
116
+ # # AllowParenthesesInCamelCaseMethod: false (default)
117
+ #
118
+ # # bad
119
+ # Array(1)
120
+ #
121
+ # # good
122
+ # Array 1
123
+ #
124
+ # # AllowParenthesesInCamelCaseMethod: true
125
+ #
126
+ # # good
127
+ # Array(1)
128
+ #
129
+ # # good
130
+ # Array 1
109
131
  class MethodCallWithArgsParentheses < Cop
110
132
  include ConfigurableEnforcedStyle
111
133
  include IgnoredMethods
@@ -120,6 +142,7 @@ module RuboCop
120
142
  add_offense_for_omit_parentheses(node)
121
143
  end
122
144
  end
145
+ alias on_csend on_send
123
146
  alias on_super on_send
124
147
  alias on_yield on_send
125
148
 
@@ -155,7 +178,7 @@ module RuboCop
155
178
  return unless node.parenthesized?
156
179
  return if node.implicit_call?
157
180
  return if super_call_without_arguments?(node)
158
- return if camel_case_method_call_without_arguments?(node)
181
+ return if allowed_camel_case_method_call?(node)
159
182
  return if legitimate_call_with_parentheses?(node)
160
183
 
161
184
  add_offense(node, location: node.loc.begin.join(node.loc.end))
@@ -221,8 +244,10 @@ module RuboCop
221
244
  node.super_type? && node.arguments.none?
222
245
  end
223
246
 
224
- def camel_case_method_call_without_arguments?(node)
225
- node.camel_case_method? && node.arguments.none?
247
+ def allowed_camel_case_method_call?(node)
248
+ node.camel_case_method? &&
249
+ (node.arguments.none? ||
250
+ cop_config['AllowParenthesesInCamelCaseMethod'])
226
251
  end
227
252
 
228
253
  def legitimate_call_with_parentheses?(node)
@@ -264,13 +289,14 @@ module RuboCop
264
289
  end
265
290
 
266
291
  def call_with_braced_block?(node)
267
- node.send_type? && node.block_node && node.block_node.braces?
292
+ (node.send_type? || node.super_type?) &&
293
+ node.block_node && node.block_node.braces?
268
294
  end
269
295
 
270
296
  def call_as_argument_or_chain?(node)
271
297
  node.parent &&
272
298
  (node.parent.send_type? && !assigned_before?(node.parent, node) ||
273
- node.parent.csend_type?)
299
+ node.parent.csend_type? || node.parent.super_type?)
274
300
  end
275
301
 
276
302
  def hash_literal_in_arguments?(node)
@@ -39,6 +39,7 @@ module RuboCop
39
39
 
40
40
  add_offense(nil, location: range)
41
41
  end
42
+ alias on_csend on_send
42
43
  end
43
44
  end
44
45
  end
@@ -20,7 +20,7 @@ module RuboCop
20
20
  def on_send(node)
21
21
  return unless node.parenthesized?
22
22
 
23
- node.each_child_node(:send) do |nested|
23
+ node.each_child_node(:send, :csend) do |nested|
24
24
  next if allowed_omission?(nested)
25
25
 
26
26
  add_offense(nested,
@@ -28,6 +28,7 @@ module RuboCop
28
28
  message: format(MSG, source: nested.source))
29
29
  end
30
30
  end
31
+ alias on_csend on_send
31
32
 
32
33
  def autocorrect(nested)
33
34
  first_arg = nested.first_argument.source_range
@@ -67,6 +67,8 @@ module RuboCop
67
67
  end
68
68
 
69
69
  def expr_replacement(node)
70
+ return 'nil' if node.nil?
71
+
70
72
  requires_parentheses?(node) ? "(#{node.source})" : node.source
71
73
  end
72
74
 
@@ -41,6 +41,7 @@ module RuboCop
41
41
 
42
42
  add_offense(node, location: :selector)
43
43
  end
44
+ alias on_csend on_send
44
45
 
45
46
  def autocorrect(node)
46
47
  lambda do |corrector|
@@ -17,13 +17,14 @@ module RuboCop
17
17
  MSG = 'Prefer `Object#__send__` or `Object#public_send` to ' \
18
18
  '`send`.'.freeze
19
19
 
20
- def_node_matcher :sending?, '(send _ :send ...)'
20
+ def_node_matcher :sending?, '({send csend} _ :send ...)'
21
21
 
22
22
  def on_send(node)
23
23
  return unless sending?(node) && node.arguments?
24
24
 
25
25
  add_offense(node, location: :selector)
26
26
  end
27
+ alias on_csend on_send
27
28
  end
28
29
  end
29
30
  end
@@ -24,6 +24,7 @@ module RuboCop
24
24
 
25
25
  add_offense(node, location: :selector)
26
26
  end
27
+ alias on_csend on_send
27
28
 
28
29
  def autocorrect(node)
29
30
  lambda do |corrector|
@@ -59,6 +59,7 @@ module RuboCop
59
59
  node.last_argument.source_range.end_pos,
60
60
  node.source_range.end_pos)
61
61
  end
62
+ alias on_csend on_send
62
63
 
63
64
  def autocorrect(range)
64
65
  PunctuationCorrector.swap_comma(range)
@@ -96,8 +96,9 @@ module RuboCop
96
96
  end
97
97
 
98
98
  def make_ternary_form(node)
99
- ternary_form = [node.if_branch.source,
100
- else_source(node.else_branch)].join(' || ')
99
+ _condition, if_branch, else_branch = *node
100
+ ternary_form = [if_branch.source,
101
+ else_source(else_branch)].join(' || ')
101
102
 
102
103
  if node.parent && node.parent.send_type?
103
104
  "(#{ternary_form})"
@@ -97,11 +97,6 @@ module RuboCop
97
97
  !noncommutative_operator?(node)
98
98
  end
99
99
 
100
- def both_literals?(node)
101
- lhs, _operator, rhs = *node
102
- lhs.literal? && rhs.literal?
103
- end
104
-
105
100
  def valid_yoda?(node)
106
101
  lhs, _operator, rhs = *node
107
102
 
@@ -5,7 +5,7 @@ module RuboCop
5
5
  # on.
6
6
  module Platform
7
7
  def self.windows?
8
- RUBY_PLATFORM =~ /cygwin|mswin|mingw|bccwin|wince|emx/
8
+ RbConfig::CONFIG['host_os'] =~ /cygwin|mswin|mingw|bccwin|wince|emx/
9
9
  end
10
10
  end
11
11
  end
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  # This module holds the RuboCop version information.
5
5
  module Version
6
- STRING = '0.63.1'.freeze
6
+ STRING = '0.64.0'.freeze
7
7
 
8
8
  MSG = '%<version>s (using Parser %<parser_version>s, running on ' \
9
9
  '%<ruby_engine>s %<ruby_version>s %<ruby_platform>s)'.freeze
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubocop
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.63.1
4
+ version: 0.64.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bozhidar Batsov
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: exe
12
12
  cert_chain: []
13
- date: 2019-01-22 00:00:00.000000000 Z
13
+ date: 2019-02-10 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: jaro_winkler
@@ -572,6 +572,7 @@ files:
572
572
  - lib/rubocop/cop/rails/present.rb
573
573
  - lib/rubocop/cop/rails/read_write_attribute.rb
574
574
  - lib/rubocop/cop/rails/redundant_receiver_in_with_options.rb
575
+ - lib/rubocop/cop/rails/reflection_class_name.rb
575
576
  - lib/rubocop/cop/rails/refute_methods.rb
576
577
  - lib/rubocop/cop/rails/relative_date_constant.rb
577
578
  - lib/rubocop/cop/rails/request_referer.rb