rubocop 0.42.0 → 0.43.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of rubocop might be problematic. Click here for more details.

Files changed (221) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/assets/output.html.erb +21 -10
  4. data/config/default.yml +32 -2
  5. data/config/disabled.yml +8 -1
  6. data/config/enabled.yml +40 -12
  7. data/lib/rubocop.rb +14 -2
  8. data/lib/rubocop/ast_node.rb +2 -0
  9. data/lib/rubocop/cached_data.rb +13 -11
  10. data/lib/rubocop/cli.rb +5 -5
  11. data/lib/rubocop/config.rb +68 -24
  12. data/lib/rubocop/config_loader.rb +13 -11
  13. data/lib/rubocop/config_loader_resolver.rb +4 -2
  14. data/lib/rubocop/cop/cop.rb +16 -5
  15. data/lib/rubocop/cop/lint/assignment_in_condition.rb +21 -20
  16. data/lib/rubocop/cop/lint/block_alignment.rb +3 -4
  17. data/lib/rubocop/cop/lint/def_end_alignment.rb +2 -3
  18. data/lib/rubocop/cop/lint/duplicate_methods.rb +16 -6
  19. data/lib/rubocop/cop/lint/else_layout.rb +1 -1
  20. data/lib/rubocop/cop/lint/empty_interpolation.rb +1 -1
  21. data/lib/rubocop/cop/lint/end_alignment.rb +4 -6
  22. data/lib/rubocop/cop/lint/eval.rb +1 -1
  23. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +1 -1
  24. data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +8 -8
  25. data/lib/rubocop/cop/lint/inherit_exception.rb +22 -7
  26. data/lib/rubocop/cop/lint/literal_in_condition.rb +5 -5
  27. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +3 -5
  28. data/lib/rubocop/cop/lint/next_without_accumulator.rb +1 -1
  29. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +9 -8
  30. data/lib/rubocop/cop/lint/percent_string_array.rb +17 -6
  31. data/lib/rubocop/cop/lint/percent_symbol_array.rb +4 -4
  32. data/lib/rubocop/cop/lint/rand_one.rb +3 -3
  33. data/lib/rubocop/cop/lint/require_parentheses.rb +1 -3
  34. data/lib/rubocop/cop/lint/shadowed_exception.rb +39 -44
  35. data/lib/rubocop/cop/lint/string_conversion_in_interpolation.rb +2 -2
  36. data/lib/rubocop/cop/lint/underscore_prefixed_variable_name.rb +1 -2
  37. data/lib/rubocop/cop/lint/unified_integer.rb +38 -0
  38. data/lib/rubocop/cop/lint/unneeded_disable.rb +51 -38
  39. data/lib/rubocop/cop/lint/unneeded_splat_expansion.rb +114 -0
  40. data/lib/rubocop/cop/lint/useless_assignment.rb +25 -12
  41. data/lib/rubocop/cop/lint/useless_setter_call.rb +27 -28
  42. data/lib/rubocop/cop/lint/void.rb +2 -4
  43. data/lib/rubocop/cop/mixin/access_modifier_node.rb +5 -5
  44. data/lib/rubocop/cop/mixin/array_hash_indentation.rb +19 -17
  45. data/lib/rubocop/cop/mixin/autocorrect_alignment.rb +3 -5
  46. data/lib/rubocop/cop/mixin/configurable_naming.rb +4 -5
  47. data/lib/rubocop/cop/mixin/configurable_numbering.rb +52 -0
  48. data/lib/rubocop/cop/mixin/def_node.rb +28 -0
  49. data/lib/rubocop/cop/mixin/documentation_comment.rb +41 -0
  50. data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +18 -13
  51. data/lib/rubocop/cop/mixin/if_node.rb +6 -0
  52. data/lib/rubocop/cop/mixin/match_range.rb +2 -5
  53. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +2 -2
  54. data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +40 -28
  55. data/lib/rubocop/cop/mixin/negative_conditional.rb +6 -6
  56. data/lib/rubocop/cop/mixin/percent_literal.rb +1 -5
  57. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +14 -4
  58. data/lib/rubocop/cop/mixin/safe_mode.rb +23 -0
  59. data/lib/rubocop/cop/mixin/space_before_punctuation.rb +2 -4
  60. data/lib/rubocop/cop/mixin/space_inside.rb +1 -3
  61. data/lib/rubocop/cop/mixin/statement_modifier.rb +30 -20
  62. data/lib/rubocop/cop/mixin/trailing_comma.rb +19 -17
  63. data/lib/rubocop/cop/performance/case_when_splat.rb +16 -41
  64. data/lib/rubocop/cop/performance/casecmp.rb +28 -16
  65. data/lib/rubocop/cop/performance/count.rb +58 -34
  66. data/lib/rubocop/cop/performance/detect.rb +3 -7
  67. data/lib/rubocop/cop/performance/double_start_end_with.rb +17 -13
  68. data/lib/rubocop/cop/performance/fixed_size.rb +19 -14
  69. data/lib/rubocop/cop/performance/flat_map.rb +16 -9
  70. data/lib/rubocop/cop/performance/hash_each.rb +2 -3
  71. data/lib/rubocop/cop/performance/lstrip_rstrip.rb +4 -6
  72. data/lib/rubocop/cop/performance/redundant_match.rb +4 -1
  73. data/lib/rubocop/cop/performance/redundant_merge.rb +63 -32
  74. data/lib/rubocop/cop/performance/redundant_sort_by.rb +8 -7
  75. data/lib/rubocop/cop/performance/reverse_each.rb +1 -4
  76. data/lib/rubocop/cop/performance/size.rb +21 -8
  77. data/lib/rubocop/cop/performance/sort_with_block.rb +54 -0
  78. data/lib/rubocop/cop/performance/string_replacement.rb +3 -7
  79. data/lib/rubocop/cop/rails/delegate.rb +2 -3
  80. data/lib/rubocop/cop/rails/find_by.rb +4 -8
  81. data/lib/rubocop/cop/rails/not_null_column.rb +45 -0
  82. data/lib/rubocop/cop/rails/request_referer.rb +3 -3
  83. data/lib/rubocop/cop/rails/safe_navigation.rb +89 -0
  84. data/lib/rubocop/cop/rails/save_bang.rb +78 -9
  85. data/lib/rubocop/cop/rails/scope_args.rb +3 -1
  86. data/lib/rubocop/cop/rails/uniq_before_pluck.rb +2 -3
  87. data/lib/rubocop/cop/rails/validation.rb +1 -1
  88. data/lib/rubocop/cop/security/json_load.rb +36 -0
  89. data/lib/rubocop/cop/style/alias.rb +1 -1
  90. data/lib/rubocop/cop/style/align_hash.rb +25 -14
  91. data/lib/rubocop/cop/style/and_or.rb +13 -3
  92. data/lib/rubocop/cop/style/array_join.rb +3 -3
  93. data/lib/rubocop/cop/style/ascii_comments.rb +1 -2
  94. data/lib/rubocop/cop/style/ascii_identifiers.rb +1 -2
  95. data/lib/rubocop/cop/style/attr.rb +1 -3
  96. data/lib/rubocop/cop/style/block_comments.rb +2 -6
  97. data/lib/rubocop/cop/style/block_delimiters.rb +35 -21
  98. data/lib/rubocop/cop/style/braces_around_hash_parameters.rb +4 -4
  99. data/lib/rubocop/cop/style/case_indentation.rb +1 -3
  100. data/lib/rubocop/cop/style/class_methods.rb +3 -4
  101. data/lib/rubocop/cop/style/collection_methods.rb +1 -1
  102. data/lib/rubocop/cop/style/command_literal.rb +15 -8
  103. data/lib/rubocop/cop/style/comment_annotation.rb +1 -2
  104. data/lib/rubocop/cop/style/conditional_assignment.rb +68 -36
  105. data/lib/rubocop/cop/style/copyright.rb +1 -5
  106. data/lib/rubocop/cop/style/def_with_parentheses.rb +3 -5
  107. data/lib/rubocop/cop/style/documentation.rb +28 -56
  108. data/lib/rubocop/cop/style/documentation_method.rb +80 -0
  109. data/lib/rubocop/cop/style/each_for_simple_loop.rb +6 -5
  110. data/lib/rubocop/cop/style/each_with_object.rb +2 -2
  111. data/lib/rubocop/cop/style/else_alignment.rb +10 -9
  112. data/lib/rubocop/cop/style/empty_case_condition.rb +2 -4
  113. data/lib/rubocop/cop/style/empty_else.rb +1 -4
  114. data/lib/rubocop/cop/style/empty_line_between_defs.rb +1 -3
  115. data/lib/rubocop/cop/style/empty_lines_around_access_modifier.rb +2 -5
  116. data/lib/rubocop/cop/style/encoding.rb +28 -14
  117. data/lib/rubocop/cop/style/even_odd.rb +28 -17
  118. data/lib/rubocop/cop/style/extra_spacing.rb +36 -25
  119. data/lib/rubocop/cop/style/file_name.rb +19 -10
  120. data/lib/rubocop/cop/style/first_parameter_indentation.rb +2 -3
  121. data/lib/rubocop/cop/style/for.rb +12 -8
  122. data/lib/rubocop/cop/style/format_string.rb +1 -1
  123. data/lib/rubocop/cop/style/guard_clause.rb +22 -56
  124. data/lib/rubocop/cop/style/hash_syntax.rb +72 -7
  125. data/lib/rubocop/cop/style/if_unless_modifier.rb +23 -19
  126. data/lib/rubocop/cop/style/if_unless_modifier_of_if_unless.rb +3 -3
  127. data/lib/rubocop/cop/style/indentation_width.rb +30 -16
  128. data/lib/rubocop/cop/style/infinite_loop.rb +16 -13
  129. data/lib/rubocop/cop/style/initial_indentation.rb +23 -18
  130. data/lib/rubocop/cop/style/inline_comment.rb +16 -3
  131. data/lib/rubocop/cop/style/lambda.rb +22 -10
  132. data/lib/rubocop/cop/style/leading_comment_space.rb +12 -1
  133. data/lib/rubocop/cop/style/line_end_concatenation.rb +24 -6
  134. data/lib/rubocop/cop/style/method_call_parentheses.rb +18 -9
  135. data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +3 -4
  136. data/lib/rubocop/cop/style/method_def_parentheses.rb +3 -4
  137. data/lib/rubocop/cop/style/method_missing.rb +10 -2
  138. data/lib/rubocop/cop/style/module_function.rb +14 -6
  139. data/lib/rubocop/cop/style/multiline_assignment_layout.rb +2 -5
  140. data/lib/rubocop/cop/style/multiline_block_chain.rb +3 -5
  141. data/lib/rubocop/cop/style/multiline_block_layout.rb +22 -15
  142. data/lib/rubocop/cop/style/multiline_method_call_brace_layout.rb +9 -0
  143. data/lib/rubocop/cop/style/multiline_method_call_indentation.rb +41 -20
  144. data/lib/rubocop/cop/style/multiline_operation_indentation.rb +6 -6
  145. data/lib/rubocop/cop/style/multiline_ternary_operator.rb +3 -5
  146. data/lib/rubocop/cop/style/mutable_constant.rb +21 -13
  147. data/lib/rubocop/cop/style/negated_if.rb +1 -1
  148. data/lib/rubocop/cop/style/negated_while.rb +3 -3
  149. data/lib/rubocop/cop/style/nested_modifier.rb +2 -4
  150. data/lib/rubocop/cop/style/next.rb +4 -4
  151. data/lib/rubocop/cop/style/non_nil_check.rb +18 -10
  152. data/lib/rubocop/cop/style/numeric_literal_prefix.rb +8 -0
  153. data/lib/rubocop/cop/style/numeric_predicate.rb +9 -9
  154. data/lib/rubocop/cop/style/one_line_conditional.rb +11 -1
  155. data/lib/rubocop/cop/style/op_method.rb +1 -1
  156. data/lib/rubocop/cop/style/option_hash.rb +8 -8
  157. data/lib/rubocop/cop/style/optional_arguments.rb +21 -8
  158. data/lib/rubocop/cop/style/parallel_assignment.rb +51 -35
  159. data/lib/rubocop/cop/style/parentheses_around_condition.rb +2 -2
  160. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +1 -1
  161. data/lib/rubocop/cop/style/raise_args.rb +2 -2
  162. data/lib/rubocop/cop/style/redundant_begin.rb +1 -1
  163. data/lib/rubocop/cop/style/redundant_parentheses.rb +26 -15
  164. data/lib/rubocop/cop/style/redundant_return.rb +5 -5
  165. data/lib/rubocop/cop/style/redundant_self.rb +20 -11
  166. data/lib/rubocop/cop/style/regexp_literal.rb +16 -10
  167. data/lib/rubocop/cop/style/rescue_ensure_alignment.rb +8 -6
  168. data/lib/rubocop/cop/style/safe_navigation.rb +125 -0
  169. data/lib/rubocop/cop/style/self_assignment.rb +2 -2
  170. data/lib/rubocop/cop/style/semicolon.rb +9 -10
  171. data/lib/rubocop/cop/style/signal_exception.rb +2 -4
  172. data/lib/rubocop/cop/style/single_line_block_params.rb +1 -1
  173. data/lib/rubocop/cop/style/single_line_methods.rb +18 -11
  174. data/lib/rubocop/cop/style/space_after_method_name.rb +2 -3
  175. data/lib/rubocop/cop/style/space_after_not.rb +4 -6
  176. data/lib/rubocop/cop/style/space_around_block_parameters.rb +1 -2
  177. data/lib/rubocop/cop/style/space_around_equals_in_parameter_default.rb +1 -3
  178. data/lib/rubocop/cop/style/space_around_operators.rb +21 -16
  179. data/lib/rubocop/cop/style/space_before_block_braces.rb +2 -12
  180. data/lib/rubocop/cop/style/space_before_first_arg.rb +1 -3
  181. data/lib/rubocop/cop/style/space_inside_array_percent_literal.rb +1 -1
  182. data/lib/rubocop/cop/style/space_inside_block_braces.rb +33 -40
  183. data/lib/rubocop/cop/style/space_inside_hash_literal_braces.rb +38 -23
  184. data/lib/rubocop/cop/style/space_inside_percent_literal_delimiters.rb +1 -1
  185. data/lib/rubocop/cop/style/space_inside_string_interpolation.rb +26 -12
  186. data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +2 -4
  187. data/lib/rubocop/cop/style/symbol_array.rb +10 -10
  188. data/lib/rubocop/cop/style/symbol_proc.rb +28 -13
  189. data/lib/rubocop/cop/style/ternary_parentheses.rb +35 -5
  190. data/lib/rubocop/cop/style/trailing_blank_lines.rb +2 -4
  191. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +29 -17
  192. data/lib/rubocop/cop/style/trivial_accessors.rb +6 -6
  193. data/lib/rubocop/cop/style/unless_else.rb +2 -6
  194. data/lib/rubocop/cop/style/unneeded_capital_w.rb +8 -4
  195. data/lib/rubocop/cop/style/unneeded_interpolation.rb +4 -5
  196. data/lib/rubocop/cop/style/unneeded_percent_q.rb +13 -7
  197. data/lib/rubocop/cop/style/variable_number.rb +79 -0
  198. data/lib/rubocop/cop/style/while_until_modifier.rb +1 -1
  199. data/lib/rubocop/cop/style/word_array.rb +25 -15
  200. data/lib/rubocop/cop/style/zero_length_predicate.rb +2 -0
  201. data/lib/rubocop/cop/util.rb +23 -4
  202. data/lib/rubocop/cop/variable_force.rb +59 -25
  203. data/lib/rubocop/cop/variable_force/locatable.rb +8 -6
  204. data/lib/rubocop/cop/variable_force/variable.rb +2 -2
  205. data/lib/rubocop/cop/variable_force/variable_table.rb +3 -3
  206. data/lib/rubocop/formatter/disabled_config_formatter.rb +16 -11
  207. data/lib/rubocop/formatter/formatter_set.rb +12 -10
  208. data/lib/rubocop/formatter/worst_offenders_formatter.rb +4 -4
  209. data/lib/rubocop/node_pattern.rb +79 -35
  210. data/lib/rubocop/options.rb +4 -4
  211. data/lib/rubocop/processed_source.rb +9 -5
  212. data/lib/rubocop/remote_config.rb +14 -10
  213. data/lib/rubocop/result_cache.rb +14 -6
  214. data/lib/rubocop/runner.rb +55 -34
  215. data/lib/rubocop/string_util.rb +9 -5
  216. data/lib/rubocop/target_finder.rb +1 -1
  217. data/lib/rubocop/token.rb +1 -1
  218. data/lib/rubocop/version.rb +1 -1
  219. metadata +15 -4
  220. data/lib/rubocop/cop/lint/useless_array_splat.rb +0 -56
  221. data/lib/rubocop/cop/performance/push_splat.rb +0 -47
@@ -14,23 +14,33 @@ module RuboCop
14
14
  ASSIGNMENT_TYPES = [:lvasgn, :casgn, :cvasgn,
15
15
  :gvasgn, :ivasgn, :masgn].freeze
16
16
 
17
+ def on_if(node)
18
+ return unless eligible_node?(node)
19
+
20
+ add_offense(node, :keyword, message(node.loc.keyword.source))
21
+ end
22
+
23
+ private
24
+
25
+ def autocorrect(node)
26
+ ->(corrector) { corrector.replace(node.source_range, oneline(node)) }
27
+ end
28
+
29
+ def eligible_node?(node)
30
+ !non_eligible_if?(node) && !node.chained? &&
31
+ !nested_conditional?(node) && single_line_as_modifier?(node)
32
+ end
33
+
34
+ def non_eligible_if?(node)
35
+ ternary?(node) || modifier_if?(node) ||
36
+ elsif?(node) || if_else?(node)
37
+ end
38
+
17
39
  def message(keyword)
18
40
  "Favor modifier `#{keyword}` usage when having a single-line body." \
19
41
  ' Another good alternative is the usage of control flow `&&`/`||`.'
20
42
  end
21
43
 
22
- def on_if(node)
23
- # discard ternary ops, if/else and modifier if/unless nodes
24
- return if ternary?(node)
25
- return if modifier_if?(node)
26
- return if elsif?(node)
27
- return if if_else?(node)
28
- return if node.chained?
29
- return unless fit_within_line_as_modifier_form?(node)
30
- return if nested_conditional?(node)
31
- add_offense(node, :keyword, message(node.loc.keyword.source))
32
- end
33
-
34
44
  def parenthesize?(node)
35
45
  # Parenthesize corrected expression if changing to modifier-if form
36
46
  # would change the meaning of the parent expression
@@ -51,15 +61,9 @@ module RuboCop
51
61
  source =~ /\s*\(\s*$/
52
62
  end
53
63
 
54
- def autocorrect(node)
55
- ->(corrector) { corrector.replace(node.source_range, oneline(node)) }
56
- end
57
-
58
- private
59
-
60
64
  # returns false if the then or else children are conditionals
61
65
  def nested_conditional?(node)
62
- node.children[1, 2].any? { |child| child && child.type == :if }
66
+ node.children[1, 2].compact.any?(&:if_type?)
63
67
  end
64
68
 
65
69
  def oneline(node)
@@ -35,9 +35,9 @@ module RuboCop
35
35
  def on_if(node)
36
36
  return unless modifier_if?(node)
37
37
  _cond, body, _else = if_node_parts(node)
38
- if body.type == :if
39
- add_offense(node, :keyword, message(node.loc.keyword.source))
40
- end
38
+ return unless body.if_type?
39
+
40
+ add_offense(node, :keyword, message(node.loc.keyword.source))
41
41
  end
42
42
  end
43
43
  end
@@ -21,6 +21,8 @@ module RuboCop
21
21
  include IfNode
22
22
  include AccessModifierNode
23
23
 
24
+ SPECIAL_MODIFIERS = %w(private protected).freeze
25
+
24
26
  def on_rescue(node)
25
27
  _begin_node, *rescue_nodes, else_node = *node
26
28
  rescue_nodes.each do |rescue_node|
@@ -65,19 +67,11 @@ module RuboCop
65
67
  check_indentation(node.loc.keyword, members.first)
66
68
 
67
69
  return unless members.any? && members.first.begin_type?
68
- style =
69
- config.for_cop('Style/IndentationConsistency')['EnforcedStyle']
70
- return unless style == 'rails'
70
+ return unless indentation_consistency_style == 'rails'
71
71
 
72
- special = %w(protected private) # Extra indentation step after these.
73
- previous_modifier = nil
74
- members.first.children.each do |m|
75
- if modifier_node?(m) && special.include?(m.source)
76
- previous_modifier = m
77
- elsif previous_modifier
78
- check_indentation(previous_modifier.source_range, m, style)
79
- previous_modifier = nil
80
- end
72
+ each_member(members) do |member, previous_modifier|
73
+ check_indentation(previous_modifier, member,
74
+ indentation_consistency_style)
81
75
  end
82
76
  end
83
77
 
@@ -121,7 +115,7 @@ module RuboCop
121
115
  _condition, *branches = *node
122
116
  latest_when = nil
123
117
  branches.compact.each do |b|
124
- if b.type == :when
118
+ if b.when_type?
125
119
  # TODO: Revert to the original expression once the fix in Rubinius
126
120
  # is released.
127
121
  #
@@ -162,6 +156,26 @@ module RuboCop
162
156
 
163
157
  private
164
158
 
159
+ def each_member(members)
160
+ previous_modifier = nil
161
+ members.first.children.each do |member|
162
+ if special_modifier?(member)
163
+ previous_modifier = member
164
+ elsif previous_modifier
165
+ yield member, previous_modifier.source_range
166
+ previous_modifier = nil
167
+ end
168
+ end
169
+ end
170
+
171
+ def special_modifier?(node)
172
+ modifier_node?(node) && SPECIAL_MODIFIERS.include?(node.source)
173
+ end
174
+
175
+ def indentation_consistency_style
176
+ config.for_cop('Style/IndentationConsistency')['EnforcedStyle']
177
+ end
178
+
165
179
  def check_assignment(node, rhs)
166
180
  # If there are method calls chained to the right hand side of the
167
181
  # assignment, we let rhs be the receiver of those method calls before
@@ -208,7 +222,7 @@ module RuboCop
208
222
  def offense(body_node, indentation, style)
209
223
  # This cop only auto-corrects the first statement in a def body, for
210
224
  # example.
211
- if body_node.type == :begin && !parentheses?(body_node)
225
+ if body_node.begin_type? && !parentheses?(body_node)
212
226
  body_node = body_node.children.first
213
227
  end
214
228
 
@@ -268,11 +282,11 @@ module RuboCop
268
282
  begin_pos = expr.begin_pos
269
283
  ind = expr.begin_pos - indentation
270
284
  pos = indentation >= 0 ? ind..begin_pos : begin_pos..ind
271
- Parser::Source::Range.new(expr.source_buffer, pos.begin, pos.end)
285
+ range_between(pos.begin, pos.end)
272
286
  end
273
287
 
274
288
  def starts_with_access_modifier?(body_node)
275
- body_node.type == :begin && modifier_node?(body_node.children.first)
289
+ body_node.begin_type? && modifier_node?(body_node.children.first)
276
290
  end
277
291
 
278
292
  def configured_indentation_width
@@ -38,26 +38,29 @@ module RuboCop
38
38
 
39
39
  def autocorrect(node)
40
40
  if node.while_post_type? || node.until_post_type?
41
- _, body = *node
42
- return lambda do |corrector|
43
- corrector.replace(body.loc.begin, 'loop do')
44
- corrector.remove(body.loc.end.end.join(node.source_range.end))
45
- end
41
+ replace_begin_end_with_modifier(node)
42
+ elsif node.modifier_form?
43
+ replace_source(node.source_range, modifier_replacement(node))
44
+ else
45
+ replace_source(non_modifier_range(node), 'loop do')
46
46
  end
47
+ end
47
48
 
48
- if node.modifier_form?
49
- range = node.source_range
50
- replacement = modifier_replacement(node)
51
- else
52
- range = non_modifier_range(node)
53
- replacement = 'loop do'
49
+ private
50
+
51
+ def replace_begin_end_with_modifier(node)
52
+ _, body = *node
53
+
54
+ lambda do |corrector|
55
+ corrector.replace(body.loc.begin, 'loop do')
56
+ corrector.remove(body.loc.end.end.join(node.source_range.end))
54
57
  end
58
+ end
55
59
 
60
+ def replace_source(range, replacement)
56
61
  ->(corrector) { corrector.replace(range, replacement) }
57
62
  end
58
63
 
59
- private
60
-
61
64
  def modifier_replacement(node)
62
65
  _, body = *node
63
66
  if node.single_line?
@@ -9,29 +9,34 @@ module RuboCop
9
9
  class InitialIndentation < Cop
10
10
  MSG = 'Indentation of first line in file detected.'.freeze
11
11
 
12
- def investigate(processed_source)
13
- first_token = processed_source.tokens.find do |t|
14
- !t.text.start_with?('#')
15
- end
16
- return unless first_token
17
- return if first_token.pos.column.zero?
18
-
19
- with_space = range_with_surrounding_space(first_token.pos, :left,
20
- !:with_newline)
21
- # If the file starts with a byte order mark (BOM), the column can be
22
- # non-zero, but then we find out here if there's no space to the left
23
- # of the first token.
24
- return if with_space == first_token.pos
25
-
26
- space = Parser::Source::Range.new(processed_source.buffer,
27
- with_space.begin_pos,
28
- first_token.pos.begin_pos)
29
- add_offense(space, first_token.pos)
12
+ def investigate(_processed_source)
13
+ token = first_token
14
+ space_before(token) { |space| add_offense(space, token.pos) }
30
15
  end
31
16
 
32
17
  def autocorrect(range)
33
18
  ->(corrector) { corrector.remove(range) }
34
19
  end
20
+
21
+ private
22
+
23
+ def first_token
24
+ processed_source.tokens.find { |t| !t.text.start_with?('#') }
25
+ end
26
+
27
+ def space_before(token)
28
+ return unless token
29
+ return if token.pos.column.zero?
30
+
31
+ token_with_space =
32
+ range_with_surrounding_space(token.pos, :left, false)
33
+ # If the file starts with a byte order mark (BOM), the column can be
34
+ # non-zero, but then we find out here if there's no space to the left
35
+ # of the first token.
36
+ return if token_with_space == token.pos
37
+
38
+ yield range_between(token_with_space.begin_pos, token.pos.begin_pos)
39
+ end
35
40
  end
36
41
  end
37
42
  end
@@ -4,13 +4,26 @@
4
4
  module RuboCop
5
5
  module Cop
6
6
  module Style
7
- # This cop checks for inline comments.
7
+ # This cop checks for trailing inline comments.
8
+ #
9
+ # @example
10
+ #
11
+ # # good
12
+ # foo.each do |f|
13
+ # # Standalone comment
14
+ # f.bar
15
+ # end
16
+ #
17
+ # # bad
18
+ # foo.each do |f|
19
+ # f.bar # Trailing inline comment
20
+ # end
8
21
  class InlineComment < Cop
9
- MSG = 'Avoid inline comments.'.freeze
22
+ MSG = 'Avoid trailing inline comments.'.freeze
10
23
 
11
24
  def investigate(processed_source)
12
25
  processed_source.comments.each do |comment|
13
- next unless comment.inline?
26
+ next if comment_line?(processed_source[comment.loc.line - 1])
14
27
  add_offense(comment, :expression)
15
28
  end
16
29
  end
@@ -92,10 +92,9 @@ module RuboCop
92
92
 
93
93
  selector = block_method.source
94
94
 
95
- if offending_selector?(node, selector)
96
- add_offense(node, block_method.source_range,
97
- message(node, selector))
98
- end
95
+ return unless offending_selector?(node, selector)
96
+
97
+ add_offense(node, block_method.source_range, message(node, selector))
99
98
  end
100
99
 
101
100
  def offending_selector?(node, selector)
@@ -166,23 +165,36 @@ module RuboCop
166
165
 
167
166
  def needs_whitespace?(block_method, args, node)
168
167
  selector_end = block_method.loc.selector.end.end_pos
169
- args_begin = args.loc.begin && args.loc.begin.begin_pos
170
- args_end = args.loc.end && args.loc.end.end_pos
171
168
  block_begin = node.loc.begin.begin_pos
172
- (block_begin == args_end && selector_end == args_begin) ||
169
+
170
+ (block_begin == end_pos(args) && selector_end == begin_pos(args)) ||
173
171
  (block_begin == selector_end)
174
172
  end
175
173
 
174
+ def begin_pos(node)
175
+ node.loc.begin && node.loc.begin.begin_pos
176
+ end
177
+
178
+ def end_pos(node)
179
+ node.loc.end && node.loc.end.end_pos
180
+ end
181
+
176
182
  def lambda_arg_string(args)
177
183
  args.children.map(&:source).join(', ')
178
184
  end
179
185
 
180
- def arg_to_unparenthesized_call?(node)
181
- parent = node.parent
186
+ def arg_to_unparenthesized_call?(arg_node)
187
+ parent = arg_node.parent
188
+
189
+ if parent && parent.pair_type?
190
+ arg_node = parent.parent
191
+ parent = arg_node.parent
192
+ end
193
+
182
194
  return false unless parent && parent.send_type?
183
195
  return false if parenthesized_call?(parent)
184
196
 
185
- node.sibling_index > 1
197
+ arg_node.sibling_index > 1
186
198
  end
187
199
 
188
200
  def remove_unparenthesized_whitespaces(corrector, node)
@@ -17,6 +17,11 @@ module RuboCop
17
17
  next unless comment.text =~ /\A#+[^#\s=:+-]/
18
18
  next if comment.text.start_with?('#!') && comment.loc.line == 1
19
19
 
20
+ # in config.ru files, if the first line starts with #\ it is treated
21
+ # as options (e.g. `#\ -p 8765` sets the request port to 8765)
22
+ next if comment.text.start_with?('#\\') && comment.loc.line == 1 &&
23
+ config_ru?(processed_source.buffer.name)
24
+
20
25
  add_offense(comment, :expression)
21
26
  end
22
27
  end
@@ -24,9 +29,15 @@ module RuboCop
24
29
  def autocorrect(comment)
25
30
  expr = comment.loc.expression
26
31
  b = expr.begin_pos
27
- hash_mark = Parser::Source::Range.new(expr.source_buffer, b, b + 1)
32
+ hash_mark = range_between(b, b + 1)
28
33
  ->(corrector) { corrector.insert_after(hash_mark, ' ') }
29
34
  end
35
+
36
+ private
37
+
38
+ def config_ru?(file_path)
39
+ File.basename(file_path).eql?('config.ru')
40
+ end
30
41
  end
31
42
  end
32
43
  end
@@ -53,19 +53,37 @@ module RuboCop
53
53
 
54
54
  def check_token_set(index)
55
55
  predecessor, operator, successor = processed_source.tokens[index, 3]
56
- return unless successor
57
- return unless CONCAT_TOKEN_TYPES.include?(operator.type)
58
- return unless standard_string_literal?(predecessor)
59
- return unless standard_string_literal?(successor)
56
+
57
+ return unless eligible_successor?(successor) &&
58
+ eligible_operator?(operator) &&
59
+ eligible_predecessor?(predecessor)
60
+
60
61
  return if operator.pos.line == successor.pos.line
61
62
 
62
63
  next_successor = token_after_last_string(successor, index)
63
- return if next_successor &&
64
- HIGH_PRECEDENCE_OP_TOKEN_TYPES.include?(next_successor.type)
64
+
65
+ return unless eligible_next_successor?(next_successor)
65
66
 
66
67
  add_offense(operator.pos, operator.pos)
67
68
  end
68
69
 
70
+ def eligible_successor?(successor)
71
+ successor && standard_string_literal?(successor)
72
+ end
73
+
74
+ def eligible_operator?(operator)
75
+ CONCAT_TOKEN_TYPES.include?(operator.type)
76
+ end
77
+
78
+ def eligible_next_successor?(next_successor)
79
+ !(next_successor &&
80
+ HIGH_PRECEDENCE_OP_TOKEN_TYPES.include?(next_successor.type))
81
+ end
82
+
83
+ def eligible_predecessor?(predecessor)
84
+ standard_string_literal?(predecessor)
85
+ end
86
+
69
87
  def token_after_last_string(successor, base_index)
70
88
  index = base_index + 3
71
89
  begin_token, end_token = COMPLEX_STRING_EDGE_TOKEN_TYPES
@@ -36,6 +36,16 @@ module RuboCop
36
36
  def same_name_assignment?(node)
37
37
  _receiver, method_name, *_args = *node
38
38
 
39
+ any_assignment?(node) do |asgn_node|
40
+ if asgn_node.masgn_type?
41
+ next variable_in_mass_assignment?(method_name, asgn_node)
42
+ end
43
+
44
+ asgn_node.loc.name.source == method_name.to_s
45
+ end
46
+ end
47
+
48
+ def any_assignment?(node)
39
49
  node.each_ancestor(*ASGN_NODES).any? do |asgn_node|
40
50
  # `obj.method = value` parses as (send ... :method= ...), and will
41
51
  # not be returned as an `asgn_node` here, however,
@@ -45,19 +55,18 @@ module RuboCop
45
55
  if asgn_node.or_asgn_type? || asgn_node.and_asgn_type? ||
46
56
  asgn_node.op_asgn_type?
47
57
  asgn_node, _value = *asgn_node
48
- return false if asgn_node.send_type?
58
+ next if asgn_node.send_type?
49
59
  end
50
60
 
51
- if asgn_node.masgn_type?
52
- mlhs_node, _mrhs_node = *asgn_node
53
- var_nodes = *mlhs_node
54
- vars = var_nodes.map { |n| (_b = *n).first }
61
+ yield asgn_node
62
+ end
63
+ end
55
64
 
56
- return vars.include?(method_name)
57
- end
65
+ def variable_in_mass_assignment?(variable_name, node)
66
+ mlhs_node, _mrhs_node = *node
67
+ var_nodes = *mlhs_node
58
68
 
59
- asgn_node.loc.name.source == method_name.to_s
60
- end
69
+ var_nodes.map { |n| n.to_a.first }.include?(variable_name)
61
70
  end
62
71
 
63
72
  # don't check `lambda.()` syntax; the Style/LambdaCall cop does that