rubocop 0.63.1 → 0.64.0

Sign up to get free protection for your applications and to get access to all the features.
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