rubocop 0.28.0 → 0.29.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 (211) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop_todo.yml +7 -7
  3. data/.travis.yml +4 -0
  4. data/CHANGELOG.md +59 -0
  5. data/README.md +62 -28
  6. data/config/default.yml +31 -0
  7. data/config/disabled.yml +1 -1
  8. data/config/enabled.yml +17 -0
  9. data/lib/rubocop.rb +4 -0
  10. data/lib/rubocop/cli.rb +1 -1
  11. data/lib/rubocop/config.rb +12 -8
  12. data/lib/rubocop/config_loader.rb +20 -10
  13. data/lib/rubocop/cop/cop.rb +13 -7
  14. data/lib/rubocop/cop/corrector.rb +10 -10
  15. data/lib/rubocop/cop/lint/assignment_in_condition.rb +6 -1
  16. data/lib/rubocop/cop/lint/block_alignment.rb +9 -2
  17. data/lib/rubocop/cop/lint/debugger.rb +13 -1
  18. data/lib/rubocop/cop/lint/duplicate_methods.rb +104 -0
  19. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +1 -1
  20. data/lib/rubocop/cop/lint/require_parentheses.rb +3 -3
  21. data/lib/rubocop/cop/mixin/access_modifier_node.rb +27 -0
  22. data/lib/rubocop/cop/mixin/on_normal_if_unless.rb +0 -4
  23. data/lib/rubocop/cop/rails/delegate.rb +4 -5
  24. data/lib/rubocop/cop/rails/read_write_attribute.rb +33 -0
  25. data/lib/rubocop/cop/style/access_modifier_indentation.rb +0 -7
  26. data/lib/rubocop/cop/style/braces_around_hash_parameters.rb +4 -2
  27. data/lib/rubocop/cop/style/class_methods.rb +25 -9
  28. data/lib/rubocop/cop/style/empty_lines_around_access_modifier.rb +7 -1
  29. data/lib/rubocop/cop/style/empty_literal.rb +25 -10
  30. data/lib/rubocop/cop/style/even_odd.rb +32 -14
  31. data/lib/rubocop/cop/style/first_parameter_indentation.rb +106 -0
  32. data/lib/rubocop/cop/style/format_string.rb +2 -2
  33. data/lib/rubocop/cop/style/global_vars.rb +1 -5
  34. data/lib/rubocop/cop/style/hash_syntax.rb +0 -4
  35. data/lib/rubocop/cop/style/indentation_consistency.rb +5 -5
  36. data/lib/rubocop/cop/style/indentation_width.rb +13 -14
  37. data/lib/rubocop/cop/style/lambda.rb +48 -2
  38. data/lib/rubocop/cop/style/line_end_concatenation.rb +43 -47
  39. data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +3 -3
  40. data/lib/rubocop/cop/style/module_function.rb +3 -3
  41. data/lib/rubocop/cop/style/multiline_block_layout.rb +65 -17
  42. data/lib/rubocop/cop/style/multiline_operation_indentation.rb +2 -1
  43. data/lib/rubocop/cop/style/perl_backrefs.rb +2 -2
  44. data/lib/rubocop/cop/style/redundant_exception.rb +12 -0
  45. data/lib/rubocop/cop/style/self_assignment.rb +27 -0
  46. data/lib/rubocop/cop/style/semicolon.rb +2 -1
  47. data/lib/rubocop/cop/style/space_around_block_parameters.rb +92 -0
  48. data/lib/rubocop/cop/style/string_literals_in_interpolation.rb +0 -8
  49. data/lib/rubocop/cop/style/struct_inheritance.rb +42 -0
  50. data/lib/rubocop/cop/style/trivial_accessors.rb +10 -4
  51. data/lib/rubocop/cop/util.rb +32 -7
  52. data/lib/rubocop/formatter/simple_text_formatter.rb +0 -15
  53. data/lib/rubocop/options.rb +28 -41
  54. data/lib/rubocop/processed_source.rb +6 -0
  55. data/lib/rubocop/rake_task.rb +6 -3
  56. data/lib/rubocop/runner.rb +55 -15
  57. data/lib/rubocop/version.rb +1 -1
  58. data/relnotes/v0.29.0.md +116 -0
  59. data/rubocop.gemspec +3 -3
  60. data/spec/rubocop/cli_spec.rb +329 -25
  61. data/spec/rubocop/config_loader_spec.rb +20 -0
  62. data/spec/rubocop/cop/lint/assignment_in_condition_spec.rb +27 -3
  63. data/spec/rubocop/cop/lint/block_alignment_spec.rb +3 -4
  64. data/spec/rubocop/cop/lint/condition_position_spec.rb +1 -1
  65. data/spec/rubocop/cop/lint/debugger_spec.rb +20 -7
  66. data/spec/rubocop/cop/lint/duplicate_methods_spec.rb +189 -0
  67. data/spec/rubocop/cop/lint/empty_interpolation_spec.rb +1 -1
  68. data/spec/rubocop/cop/lint/end_in_method_spec.rb +1 -1
  69. data/spec/rubocop/cop/lint/eval_spec.rb +4 -4
  70. data/spec/rubocop/cop/lint/literal_in_condition_spec.rb +18 -0
  71. data/spec/rubocop/cop/lint/literal_in_interpolation_spec.rb +2 -2
  72. data/spec/rubocop/cop/lint/loop_spec.rb +4 -4
  73. data/spec/rubocop/cop/lint/parentheses_as_grouped_expression_spec.rb +7 -7
  74. data/spec/rubocop/cop/lint/space_before_first_arg_spec.rb +5 -4
  75. data/spec/rubocop/cop/lint/useless_assignment_spec.rb +3 -9
  76. data/spec/rubocop/cop/lint/useless_comparison_spec.rb +1 -1
  77. data/spec/rubocop/cop/lint/void_spec.rb +1 -1
  78. data/spec/rubocop/cop/metrics/abc_size_spec.rb +10 -0
  79. data/spec/rubocop/cop/metrics/line_length_spec.rb +2 -2
  80. data/spec/rubocop/cop/metrics/parameter_lists_spec.rb +2 -2
  81. data/spec/rubocop/cop/rails/action_filter_spec.rb +6 -12
  82. data/spec/rubocop/cop/rails/default_scope_spec.rb +5 -5
  83. data/spec/rubocop/cop/rails/delegate_spec.rb +8 -0
  84. data/spec/rubocop/cop/rails/has_and_belongs_to_many_spec.rb +1 -1
  85. data/spec/rubocop/cop/rails/read_write_attribute_spec.rb +119 -8
  86. data/spec/rubocop/cop/rails/scope_args_spec.rb +3 -3
  87. data/spec/rubocop/cop/rails/validation_spec.rb +3 -3
  88. data/spec/rubocop/cop/style/alias_spec.rb +5 -5
  89. data/spec/rubocop/cop/style/align_hash_spec.rb +1 -1
  90. data/spec/rubocop/cop/style/align_parameters_spec.rb +8 -8
  91. data/spec/rubocop/cop/style/and_or_spec.rb +15 -30
  92. data/spec/rubocop/cop/style/array_join_spec.rb +4 -4
  93. data/spec/rubocop/cop/style/ascii_comments_spec.rb +1 -2
  94. data/spec/rubocop/cop/style/ascii_identifiers_spec.rb +2 -2
  95. data/spec/rubocop/cop/style/begin_block_spec.rb +1 -1
  96. data/spec/rubocop/cop/style/block_comments_spec.rb +1 -1
  97. data/spec/rubocop/cop/style/block_end_newline_spec.rb +1 -1
  98. data/spec/rubocop/cop/style/blocks_spec.rb +2 -2
  99. data/spec/rubocop/cop/style/braces_around_hash_parameters_spec.rb +38 -33
  100. data/spec/rubocop/cop/style/case_equality_spec.rb +1 -1
  101. data/spec/rubocop/cop/style/character_literal_spec.rb +4 -4
  102. data/spec/rubocop/cop/style/class_and_module_children_spec.rb +4 -2
  103. data/spec/rubocop/cop/style/class_methods_spec.rb +12 -0
  104. data/spec/rubocop/cop/style/class_vars_spec.rb +2 -2
  105. data/spec/rubocop/cop/style/collection_methods_spec.rb +4 -4
  106. data/spec/rubocop/cop/style/colon_method_call_spec.rb +8 -8
  107. data/spec/rubocop/cop/style/comment_annotation_spec.rb +10 -10
  108. data/spec/rubocop/cop/style/constant_name_spec.rb +7 -7
  109. data/spec/rubocop/cop/style/def_with_parentheses_spec.rb +1 -1
  110. data/spec/rubocop/cop/style/deprecated_hash_methods_spec.rb +4 -4
  111. data/spec/rubocop/cop/style/dot_position_spec.rb +8 -6
  112. data/spec/rubocop/cop/style/each_with_object_spec.rb +2 -2
  113. data/spec/rubocop/cop/style/else_alignment_spec.rb +2 -4
  114. data/spec/rubocop/cop/style/empty_lines_around_access_modifier_spec.rb +78 -0
  115. data/spec/rubocop/cop/style/empty_lines_around_class_body_spec.rb +60 -0
  116. data/spec/rubocop/cop/style/empty_lines_spec.rb +3 -3
  117. data/spec/rubocop/cop/style/empty_literal_spec.rb +29 -12
  118. data/spec/rubocop/cop/style/encoding_spec.rb +3 -3
  119. data/spec/rubocop/cop/style/end_block_spec.rb +1 -1
  120. data/spec/rubocop/cop/style/end_of_line_spec.rb +2 -2
  121. data/spec/rubocop/cop/style/even_odd_spec.rb +109 -20
  122. data/spec/rubocop/cop/style/extra_spacing_spec.rb +3 -3
  123. data/spec/rubocop/cop/style/first_parameter_indentation_spec.rb +293 -0
  124. data/spec/rubocop/cop/style/for_spec.rb +2 -2
  125. data/spec/rubocop/cop/style/format_string_spec.rb +45 -21
  126. data/spec/rubocop/cop/style/global_vars_spec.rb +4 -4
  127. data/spec/rubocop/cop/style/guard_clause_spec.rb +17 -0
  128. data/spec/rubocop/cop/style/hash_syntax_spec.rb +15 -15
  129. data/spec/rubocop/cop/{metrics → style}/if_unless_modifier_spec.rb +2 -2
  130. data/spec/rubocop/cop/style/if_with_semicolon_spec.rb +2 -2
  131. data/spec/rubocop/cop/style/indent_array_spec.rb +3 -6
  132. data/spec/rubocop/cop/style/indent_hash_spec.rb +4 -4
  133. data/spec/rubocop/cop/style/indentation_consistency_spec.rb +1 -2
  134. data/spec/rubocop/cop/style/indentation_width_spec.rb +1 -2
  135. data/spec/rubocop/cop/style/infinite_loop_spec.rb +1 -1
  136. data/spec/rubocop/cop/style/lambda_call_spec.rb +4 -4
  137. data/spec/rubocop/cop/style/lambda_spec.rb +37 -2
  138. data/spec/rubocop/cop/style/leading_comment_space_spec.rb +7 -12
  139. data/spec/rubocop/cop/style/line_end_concatenation_spec.rb +41 -1
  140. data/spec/rubocop/cop/style/method_call_parentheses_spec.rb +4 -4
  141. data/spec/rubocop/cop/style/method_called_on_do_end_block_spec.rb +3 -3
  142. data/spec/rubocop/cop/style/method_name_spec.rb +1 -1
  143. data/spec/rubocop/cop/style/multiline_block_layout_spec.rb +61 -0
  144. data/spec/rubocop/cop/style/multiline_if_then_spec.rb +1 -3
  145. data/spec/rubocop/cop/style/multiline_operation_indentation_spec.rb +8 -0
  146. data/spec/rubocop/cop/style/multiline_ternary_operator_spec.rb +1 -1
  147. data/spec/rubocop/cop/style/nested_ternary_operator_spec.rb +1 -1
  148. data/spec/rubocop/cop/style/next_spec.rb +16 -0
  149. data/spec/rubocop/cop/style/numeric_literals_spec.rb +5 -5
  150. data/spec/rubocop/cop/style/one_line_conditional_spec.rb +1 -1
  151. data/spec/rubocop/cop/style/parentheses_around_condition_spec.rb +22 -4
  152. data/spec/rubocop/cop/style/percent_literal_delimiters_spec.rb +31 -31
  153. data/spec/rubocop/cop/style/percent_q_literals_spec.rb +12 -12
  154. data/spec/rubocop/cop/style/perl_backrefs_spec.rb +3 -3
  155. data/spec/rubocop/cop/style/proc_spec.rb +3 -3
  156. data/spec/rubocop/cop/style/raise_args_spec.rb +9 -9
  157. data/spec/rubocop/cop/style/redundant_begin_spec.rb +1 -1
  158. data/spec/rubocop/cop/style/redundant_exception_spec.rb +36 -4
  159. data/spec/rubocop/cop/style/redundant_self_spec.rb +89 -45
  160. data/spec/rubocop/cop/style/regexp_literal_spec.rb +9 -9
  161. data/spec/rubocop/cop/style/rescue_modifier_spec.rb +2 -2
  162. data/spec/rubocop/cop/style/self_assignment_spec.rb +16 -10
  163. data/spec/rubocop/cop/style/semicolon_spec.rb +9 -9
  164. data/spec/rubocop/cop/style/single_line_block_params_spec.rb +2 -2
  165. data/spec/rubocop/cop/style/single_space_before_first_arg_spec.rb +1 -1
  166. data/spec/rubocop/cop/style/space_after_colon_spec.rb +5 -5
  167. data/spec/rubocop/cop/style/space_after_comma_spec.rb +3 -3
  168. data/spec/rubocop/cop/style/space_after_control_keyword_spec.rb +4 -4
  169. data/spec/rubocop/cop/style/space_after_not_spec.rb +2 -2
  170. data/spec/rubocop/cop/style/space_after_semicolon_spec.rb +2 -2
  171. data/spec/rubocop/cop/style/space_around_block_parameters_spec.rb +150 -0
  172. data/spec/rubocop/cop/style/space_around_equals_in_parameter_default_spec.rb +18 -9
  173. data/spec/rubocop/cop/style/space_around_operators_spec.rb +24 -21
  174. data/spec/rubocop/cop/style/space_before_block_braces_spec.rb +4 -4
  175. data/spec/rubocop/cop/style/space_before_comma_spec.rb +4 -4
  176. data/spec/rubocop/cop/style/space_before_comment_spec.rb +3 -3
  177. data/spec/rubocop/cop/style/space_before_semicolon_spec.rb +2 -2
  178. data/spec/rubocop/cop/style/space_inside_block_braces_spec.rb +33 -24
  179. data/spec/rubocop/cop/style/space_inside_brackets_spec.rb +2 -2
  180. data/spec/rubocop/cop/style/space_inside_hash_literal_braces_spec.rb +9 -9
  181. data/spec/rubocop/cop/style/space_inside_parens_spec.rb +1 -1
  182. data/spec/rubocop/cop/style/special_global_vars_spec.rb +6 -6
  183. data/spec/rubocop/cop/style/string_literals_in_interpolation_spec.rb +3 -3
  184. data/spec/rubocop/cop/style/string_literals_spec.rb +16 -16
  185. data/spec/rubocop/cop/style/struct_inheritance_spec.rb +44 -0
  186. data/spec/rubocop/cop/style/symbol_array_spec.rb +9 -9
  187. data/spec/rubocop/cop/style/symbol_proc_spec.rb +12 -12
  188. data/spec/rubocop/cop/style/tab_spec.rb +4 -4
  189. data/spec/rubocop/cop/style/trailing_blank_lines_spec.rb +2 -2
  190. data/spec/rubocop/cop/style/trailing_whitespace_spec.rb +2 -2
  191. data/spec/rubocop/cop/style/trivial_accessors_spec.rb +16 -0
  192. data/spec/rubocop/cop/style/unneeded_capital_w_spec.rb +11 -22
  193. data/spec/rubocop/cop/style/variable_interpolation_spec.rb +7 -7
  194. data/spec/rubocop/cop/style/while_until_do_spec.rb +2 -2
  195. data/spec/rubocop/cop/{metrics → style}/while_until_modifier_spec.rb +2 -2
  196. data/spec/rubocop/cop/style/word_array_spec.rb +11 -11
  197. data/spec/rubocop/cop/util_spec.rb +51 -0
  198. data/spec/rubocop/cop/variable_force/reference_spec.rb +19 -0
  199. data/spec/rubocop/cop/variable_force/variable_table_spec.rb +7 -0
  200. data/spec/rubocop/formatter/disabled_lines_formatter_spec.rb +7 -8
  201. data/spec/rubocop/formatter/text_util_spec.rb +55 -0
  202. data/spec/rubocop/options_spec.rb +26 -20
  203. data/spec/rubocop/rake_task_spec.rb +122 -0
  204. data/spec/rubocop/runner_spec.rb +37 -2
  205. data/spec/rubocop/token_spec.rb +5 -1
  206. data/spec/spec_helper.rb +5 -2
  207. data/spec/support/cop_helper.rb +3 -0
  208. data/spec/support/cops/class_must_be_a_module_cop.rb +19 -0
  209. data/spec/support/cops/module_must_be_a_class_cop.rb +19 -0
  210. data/spec/support/custom_matchers.rb +1 -1
  211. metadata +35 -12
@@ -7,11 +7,11 @@ module RuboCop
7
7
  #
8
8
  # @example
9
9
  #
10
- # class A
11
- # def test
12
- # puts 'hello'
13
- # end
14
- # end
10
+ # class A
11
+ # def test
12
+ # puts 'hello'
13
+ # end
14
+ # end
15
15
  class IndentationWidth < Cop # rubocop:disable Metrics/ClassLength
16
16
  include AutocorrectAlignment
17
17
  include OnMethodDef
@@ -128,9 +128,9 @@ module RuboCop
128
128
  return if modifier_if?(node)
129
129
 
130
130
  case node.loc.keyword.source
131
- when 'if' then _condition, body, else_clause = *node
132
- when 'unless' then _condition, else_clause, body = *node
133
- else _condition, body = *node
131
+ when 'if', 'elsif' then _condition, body, else_clause = *node
132
+ when 'unless' then _condition, else_clause, body = *node
133
+ else _condition, body = *node
134
134
  end
135
135
 
136
136
  check_if(node, body, else_clause, base.loc) if body
@@ -164,12 +164,11 @@ module RuboCop
164
164
  check_indentation(base_loc, body)
165
165
  return unless else_clause
166
166
 
167
- if elsif?(else_clause)
168
- _condition, inner_body, inner_else_clause = *else_clause
169
- check_if(else_clause, inner_body, inner_else_clause, base_loc)
170
- else
171
- check_indentation(node.loc.else, else_clause)
172
- end
167
+ # If the else clause is an elsif, it will get its own on_if call so
168
+ # we don't need to process it here.
169
+ return if elsif?(else_clause)
170
+
171
+ check_indentation(node.loc.else, else_clause)
173
172
  end
174
173
 
175
174
  def check_indentation(base_loc, body_node)
@@ -8,6 +8,7 @@ module RuboCop
8
8
  # anonymous functions.
9
9
  class Lambda < Cop
10
10
  SINGLE_MSG = 'Use the new lambda literal syntax `->(params) {...}`.'
11
+ SINGLE_NO_ARG_MSG = 'Use the new lambda literal syntax `-> {...}`.'
11
12
  MULTI_MSG = 'Use the `lambda` method for multi-line lambdas.'
12
13
 
13
14
  TARGET = s(:send, nil, :lambda)
@@ -17,14 +18,14 @@ module RuboCop
17
18
  # (block
18
19
  # (send nil :lambda)
19
20
  # ...)
20
- block_method, = *node
21
+ block_method, args, = *node
21
22
 
22
23
  return unless block_method == TARGET
23
24
  selector = block_method.loc.selector.source
24
25
  lambda_length = lambda_length(node)
25
26
 
26
27
  if selector != '->' && lambda_length == 0
27
- add_offense(block_method, :expression, SINGLE_MSG)
28
+ add_offense_for_single_line(block_method, args)
28
29
  elsif selector == '->' && lambda_length > 0
29
30
  add_offense(block_method, :expression, MULTI_MSG)
30
31
  end
@@ -32,12 +33,57 @@ module RuboCop
32
33
 
33
34
  private
34
35
 
36
+ def add_offense_for_single_line(block_method, args)
37
+ if args.children.empty?
38
+ add_offense(block_method, :expression, SINGLE_NO_ARG_MSG)
39
+ else
40
+ add_offense(block_method, :expression, SINGLE_MSG)
41
+ end
42
+ end
43
+
35
44
  def lambda_length(block_node)
36
45
  start_line = block_node.loc.begin.line
37
46
  end_line = block_node.loc.end.line
38
47
 
39
48
  end_line - start_line
40
49
  end
50
+
51
+ def autocorrect(node)
52
+ ancestor = node.ancestors.first
53
+
54
+ @corrections << lambda do |corrector|
55
+ if node.loc.expression.source == 'lambda'
56
+ autocorrect_old_to_new(corrector, ancestor)
57
+ else
58
+ autocorrect_new_to_old(corrector, ancestor)
59
+ end
60
+ end
61
+ end
62
+
63
+ def autocorrect_new_to_old(corrector, node)
64
+ block_method, args = *node
65
+ corrector.replace(block_method.loc.expression, 'lambda')
66
+ return if args.children.empty?
67
+
68
+ arg_str = " |#{lambda_arg_string(args)}|"
69
+ corrector.remove(args.loc.expression)
70
+ corrector.insert_after(node.loc.begin, arg_str)
71
+ end
72
+
73
+ def autocorrect_old_to_new(corrector, node)
74
+ block_method, args = *node
75
+ corrector.replace(block_method.loc.expression, '->')
76
+ return if args.children.empty?
77
+
78
+ arg_str = "(#{lambda_arg_string(args)})"
79
+ whitespace_and_old_args = node.loc.begin.end.join(args.loc.end)
80
+ corrector.insert_after(block_method.loc.expression, arg_str)
81
+ corrector.remove(whitespace_and_old_args)
82
+ end
83
+
84
+ def lambda_arg_string(args)
85
+ args.children.map { |a| a.loc.expression.source }.join(', ')
86
+ end
41
87
  end
42
88
  end
43
89
  end
@@ -21,70 +21,66 @@ module RuboCop
21
21
  #
22
22
  class LineEndConcatenation < Cop
23
23
  MSG = 'Use `\\` instead of `+` or `<<` to concatenate those strings.'
24
+ CONCAT_TOKEN_TYPES = [:tPLUS, :tLSHFT].freeze
25
+ SIMPLE_STRING_TOKEN_TYPE = :tSTRING
26
+ COMPLEX_STRING_EDGE_TOKEN_TYPES = [:tSTRING_BEG, :tSTRING_END].freeze
27
+ HIGH_PRECEDENCE_OP_TOKEN_TYPES = [:tSTAR2, :tPERCENT, :tDOT,
28
+ :tLBRACK2].freeze
29
+ QUOTE_DELIMITERS = %w(' ").freeze
24
30
 
25
- def on_send(node)
26
- add_offense(node, :selector) if offending_node?(node)
31
+ def investigate(processed_source)
32
+ processed_source.tokens.each_index do |index|
33
+ check_token_set(index)
34
+ end
27
35
  end
28
36
 
29
- def autocorrect(node)
37
+ def autocorrect(operator_range)
30
38
  @corrections << lambda do |corrector|
31
- # replace + with \
32
- corrector.replace(node.loc.selector, '\\')
39
+ corrector.replace(operator_range, '\\')
33
40
  end
34
41
  end
35
42
 
36
43
  private
37
44
 
38
- def concat?(method)
39
- [:+, :<<].include?(method)
40
- end
41
-
42
- def offending_node?(node)
43
- receiver, method, first_arg = *node
44
-
45
- return false unless concat?(method)
46
-
47
- return false unless final_node_is_string_type?(receiver)
48
-
49
- return false unless root_node_is_string_type?(first_arg)
45
+ def check_token_set(index)
46
+ predecessor, operator, successor = processed_source.tokens[index, 3]
47
+ return unless successor
48
+ return unless CONCAT_TOKEN_TYPES.include?(operator.type)
49
+ return unless standard_string_literal?(predecessor)
50
+ return unless standard_string_literal?(successor)
51
+ return if operator.pos.line == successor.pos.line
50
52
 
51
- expression = node.loc.expression.source
52
- concatenator_at_line_end?(expression)
53
- end
54
-
55
- def concatenator_at_line_end?(expression)
56
- # check if the first line of the expression ends with a + or a <<
57
- expression =~ /.+(\+|<<)\s*$/
58
- end
53
+ next_successor = token_after_last_string(successor, index)
54
+ return if next_successor &&
55
+ HIGH_PRECEDENCE_OP_TOKEN_TYPES.include?(next_successor.type)
59
56
 
60
- def string_type?(node)
61
- return false unless [:str, :dstr].include?(node.type)
62
- # strings like __FILE__ are of no interest
63
- return false unless node.loc.respond_to?(:begin)
64
-
65
- # we care only about quotes-delimited literals
66
- if node.loc.begin
67
- ["'", '"'].include?(node.loc.begin.source)
68
- elsif node.children.any?
69
- node.children.map { |child| string_type?(child) }.all?
70
- end
57
+ add_offense(operator.pos, operator.pos)
71
58
  end
72
59
 
73
- def final_node_is_string_type?(node)
74
- if node.type == :send
75
- _, method, first_arg = *node
76
- concat?(method) && final_node_is_string_type?(first_arg)
77
- else
78
- string_type?(node)
60
+ def token_after_last_string(successor, base_index)
61
+ index = base_index + 3
62
+ begin_token, end_token = COMPLEX_STRING_EDGE_TOKEN_TYPES
63
+ if successor.type == begin_token
64
+ ends_to_find = 1
65
+ while ends_to_find > 0
66
+ case processed_source.tokens[index].type
67
+ when begin_token then ends_to_find += 1
68
+ when end_token then ends_to_find -= 1
69
+ end
70
+ index += 1
71
+ end
79
72
  end
73
+ processed_source.tokens[index]
80
74
  end
81
75
 
82
- def root_node_is_string_type?(node)
83
- if node.type == :send
84
- receiver, method, _ = *node
85
- concat?(method) && root_node_is_string_type?(receiver)
76
+ def standard_string_literal?(token)
77
+ case token.type
78
+ when SIMPLE_STRING_TOKEN_TYPE
79
+ true
80
+ when *COMPLEX_STRING_EDGE_TOKEN_TYPES
81
+ QUOTE_DELIMITERS.include?(token.text)
86
82
  else
87
- string_type?(node)
83
+ false
88
84
  end
89
85
  end
90
86
  end
@@ -9,9 +9,9 @@ module RuboCop
9
9
  #
10
10
  # @example
11
11
  #
12
- # a do
13
- # b
14
- # end.c
12
+ # a do
13
+ # b
14
+ # end.c
15
15
  class MethodCalledOnDoEndBlock < Cop
16
16
  MSG = 'Avoid chaining a method call on a do...end block.'
17
17
 
@@ -7,10 +7,10 @@ module RuboCop
7
7
  #
8
8
  # @example
9
9
  #
10
- # module Test
11
- # extend self
10
+ # module Test
11
+ # extend self
12
12
  #
13
- # ...
13
+ # ...
14
14
  # end
15
15
  class ModuleFunction < Cop
16
16
  MSG = 'Use `module_function` instead of `extend self`.'
@@ -4,7 +4,8 @@ module RuboCop
4
4
  module Cop
5
5
  module Style
6
6
  # This cop checks whether the multiline do end blocks have a newline
7
- # after the start of the block.
7
+ # after the start of the block. Additionally, it checks whether the block
8
+ # arguments, if any, are on the same line as the start of the block.
8
9
  #
9
10
  # @example
10
11
  # # bad
@@ -12,6 +13,12 @@ module RuboCop
12
13
  # bar(i)
13
14
  # end
14
15
  #
16
+ # # bad
17
+ # blah do
18
+ # |i| foo(i)
19
+ # bar(i)
20
+ # end
21
+ #
15
22
  # # good
16
23
  # blah do |i|
17
24
  # foo(i)
@@ -30,6 +37,8 @@ module RuboCop
30
37
  # }
31
38
  class MultilineBlockLayout < Cop
32
39
  MSG = 'Block body expression is on the same line as the block start.'
40
+ ARG_MSG = 'Block argument expression is not on the same line as the ' \
41
+ 'block start.'
33
42
 
34
43
  def on_block(node)
35
44
  end_loc = node.loc.end
@@ -38,35 +47,74 @@ module RuboCop
38
47
 
39
48
  # A block node has three children: the block start,
40
49
  # the arguments, and the expression. We care if the block start
41
- # and the expression start on the same line.
42
- last_expression = node.children.last
43
- return unless last_expression
44
- expression_loc = last_expression.loc
45
- return unless do_loc.line == expression_loc.line
50
+ # with arguments and the expression start on the same line.
51
+ _block_start, args, last_expression = node.children
46
52
 
47
- expression = last_expression.loc.expression
53
+ if !args.children.empty? && do_loc.line != args.loc.end.line
54
+ add_offense_for_expression(node, args, ARG_MSG)
55
+ else
56
+ return unless last_expression
57
+ expression_loc = last_expression.loc
58
+ return unless do_loc.line == expression_loc.line
59
+ add_offense_for_expression(node, last_expression, MSG)
60
+ end
61
+ end
62
+
63
+ def add_offense_for_expression(node, expr, msg)
64
+ expression = expr.loc.expression
48
65
  range = Parser::Source::Range.new(expression.source_buffer,
49
66
  expression.begin_pos,
50
67
  expression.end_pos)
51
68
 
52
- add_offense(node, range)
69
+ add_offense(node, range, msg)
53
70
  end
54
71
 
55
72
  def autocorrect(node)
56
73
  @corrections << lambda do |corrector|
57
- _method, _args, block_body = *node
58
- first_node = if block_body.type == :begin
59
- block_body.children.first
60
- else
61
- block_body
62
- end
74
+ _method, args, block_body = *node
75
+ unless args.children.empty? ||
76
+ args.loc.end.line == node.loc.begin.line
77
+ autocorrect_arguments(corrector, node, args, block_body)
78
+ expr_before_body = args.loc.expression.end
79
+ end
63
80
 
64
- block_start_col = node.loc.expression.column
81
+ return unless block_body
65
82
 
66
- corrector.insert_before(first_node.loc.expression,
67
- "\n #{' ' * block_start_col}")
83
+ expr_before_body ||= node.loc.begin
84
+ if expr_before_body.line == block_body.loc.line
85
+ autocorrect_body(corrector, node, block_body)
86
+ end
68
87
  end
69
88
  end
89
+
90
+ def autocorrect_arguments(corrector, node, args, block_body)
91
+ end_pos = if block_body
92
+ block_body.loc.expression.begin_pos
93
+ else
94
+ node.loc.end.begin.begin_pos - 1
95
+ end
96
+ range = Parser::Source::Range.new(args.loc.expression.source_buffer,
97
+ node.loc.begin.end.begin_pos,
98
+ end_pos)
99
+ corrector.replace(range, " |#{block_arg_string(args)}|")
100
+ end
101
+
102
+ def autocorrect_body(corrector, node, block_body)
103
+ first_node = if block_body.type == :begin
104
+ block_body.children.first
105
+ else
106
+ block_body
107
+ end
108
+
109
+ block_start_col = node.loc.expression.column
110
+
111
+ corrector.insert_before(first_node.loc.expression,
112
+ "\n #{' ' * block_start_col}")
113
+ end
114
+
115
+ def block_arg_string(args)
116
+ args.children.map { |a| a.loc.expression.source }.join(', ')
117
+ end
70
118
  end
71
119
  end
72
120
  end
@@ -25,8 +25,9 @@ module RuboCop
25
25
  end
26
26
 
27
27
  def on_send(node)
28
- receiver, _method_name, *_args = *node
28
+ receiver, method_name, *_args = *node
29
29
  return unless receiver
30
+ return if method_name == :[] # Don't check parameters inside [].
30
31
 
31
32
  lhs, rhs = left_hand_side(receiver), right_hand_side(node)
32
33
  range = offending_range(node, lhs, rhs, style)
@@ -18,10 +18,10 @@ module RuboCop
18
18
  parent_type = node.parent ? node.parent.type : nil
19
19
  if [:dstr, :xstr, :regexp].include?(parent_type)
20
20
  corrector.replace(node.loc.expression,
21
- "{Regexp.last_match[#{backref}]}")
21
+ "{Regexp.last_match(#{backref})}")
22
22
  else
23
23
  corrector.replace(node.loc.expression,
24
- "Regexp.last_match[#{backref}]")
24
+ "Regexp.last_match(#{backref})")
25
25
  end
26
26
  end
27
27
  end
@@ -26,6 +26,18 @@ module RuboCop
26
26
 
27
27
  add_offense(first_arg, :expression) if first_arg == TARGET_NODE
28
28
  end
29
+
30
+ # switch `raise RuntimeError, 'message'` to `raise 'message'`
31
+ def autocorrect(node)
32
+ @corrections << lambda do |corrector|
33
+ start_range = node.loc.expression.begin
34
+ no_comma = range_with_surrounding_comma(node.loc.expression.end,
35
+ :right)
36
+ comma_range = start_range.join(no_comma)
37
+ final_range = range_with_surrounding_space(comma_range, :right)
38
+ corrector.replace(final_range, '')
39
+ end
40
+ end
29
41
  end
30
42
  end
31
43
  end
@@ -62,6 +62,33 @@ module RuboCop
62
62
  operator = rhs.loc.operator.source
63
63
  add_offense(node, :expression, format(MSG, operator))
64
64
  end
65
+
66
+ def autocorrect(node)
67
+ _var_name, rhs = *node
68
+
69
+ if rhs.type == :send
70
+ autocorrect_send_node(node, rhs)
71
+ elsif [:and, :or].include?(rhs.type)
72
+ autocorrect_boolean_node(node, rhs)
73
+ end
74
+ end
75
+
76
+ def autocorrect_send_node(node, rhs)
77
+ _receiver, method_name, args = *rhs
78
+ apply_autocorrect(node, rhs, method_name.to_s, args)
79
+ end
80
+
81
+ def autocorrect_boolean_node(node, rhs)
82
+ _first_operand, second_operand = *rhs
83
+ apply_autocorrect(node, rhs, rhs.loc.operator.source, second_operand)
84
+ end
85
+
86
+ def apply_autocorrect(node, rhs, operator, new_rhs)
87
+ @corrections << lambda do |corrector|
88
+ corrector.insert_before(node.loc.operator, operator)
89
+ corrector.replace(rhs.loc.expression, new_rhs.loc.expression.source)
90
+ end
91
+ end
65
92
  end
66
93
  end
67
94
  end