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
@@ -4,7 +4,7 @@
4
4
  module RuboCop
5
5
  module Cop
6
6
  module Style
7
- # This cop checks for places where Fixnum#even? or Fixnum#odd?
7
+ # This cop checks for places where Integer#even? or Integer#odd?
8
8
  # should have been used.
9
9
  #
10
10
  # @example
@@ -15,20 +15,25 @@ module RuboCop
15
15
  # # good
16
16
  # if x.even?
17
17
  class EvenOdd < Cop
18
- MSG = 'Replace with `Fixnum#%s?`.'.freeze
18
+ MSG = 'Replace with `Integer#%s?`.'.freeze
19
19
 
20
20
  ZERO = s(:int, 0)
21
21
  ONE = s(:int, 1)
22
22
  TWO = s(:int, 2)
23
23
 
24
+ EQUALITY_OPERATORS = [:==, :!=].freeze
25
+
24
26
  def on_send(node)
25
- offense = offense_type(node)
26
- add_offense(node, :expression, format(MSG, offense)) if offense
27
+ offense_type(node) do |replacement_method|
28
+ add_offense(node, :expression, format(MSG, replacement_method))
29
+ end
27
30
  end
28
31
 
29
32
  def autocorrect(node)
30
- correction = "#{base_number(node)}.#{offense_type(node)}?"
31
- ->(corrector) { corrector.replace(node.source_range, correction) }
33
+ offense_type(node) do |replacement_method|
34
+ correction = "#{base_number(node)}.#{replacement_method}?"
35
+ ->(corrector) { corrector.replace(node.source_range, correction) }
36
+ end
32
37
  end
33
38
 
34
39
  private
@@ -36,20 +41,20 @@ module RuboCop
36
41
  def base_number(node)
37
42
  receiver, = *node
38
43
  node = expression(receiver)
39
- node.children[0].source
44
+ node.children.first.source
40
45
  end
41
46
 
42
47
  def offense_type(node)
43
48
  receiver, method, args = *node
44
49
 
45
- return unless [:==, :!=].include?(method)
50
+ return unless equality_operator?(method)
46
51
  return unless div_by_2?(receiver)
47
52
 
48
- if args == ZERO
49
- method == :== ? :even : :odd
50
- elsif args == ONE
51
- method == :== ? :odd : :even
52
- end
53
+ replacement_method(args, method) { |odd_or_even| yield odd_or_even }
54
+ end
55
+
56
+ def equality_operator?(method_name)
57
+ EQUALITY_OPERATORS.include?(method_name)
53
58
  end
54
59
 
55
60
  def div_by_2?(node)
@@ -60,15 +65,21 @@ module RuboCop
60
65
  method == :% && args == TWO
61
66
  end
62
67
 
68
+ def replacement_method(args, method)
69
+ if args == ZERO
70
+ yield method == :== ? :even : :odd
71
+ elsif args == ONE
72
+ yield method == :== ? :odd : :even
73
+ end
74
+ end
75
+
63
76
  def expression(node)
64
77
  return unless node
65
78
 
66
79
  # check for scenarios like (x % 2) == 0
67
- if node.type == :begin && node.children.size == 1
68
- node = node.children.first
69
- end
80
+ node = node.children.first if node.begin_type? && node.children.one?
70
81
 
71
- return unless node.type == :send
82
+ return unless node.send_type?
72
83
  node
73
84
  end
74
85
  end
@@ -30,14 +30,7 @@ module RuboCop
30
30
  return if processed_source.ast.nil?
31
31
 
32
32
  if force_equal_sign_alignment?
33
- @asgn_tokens = processed_source.tokens.select { |t| equal_sign?(t) }
34
- # we don't want to operate on equals signs which are part of an
35
- # optarg in a method definition
36
- # e.g.: def method(optarg = default_val); end
37
- @asgn_tokens = remove_optarg_equals(@asgn_tokens, processed_source)
38
-
39
- # Only attempt to align the first = on each line
40
- @asgn_tokens = Set.new(@asgn_tokens.uniq { |t| t.pos.line })
33
+ @asgn_tokens = assignment_tokens
41
34
  @asgn_lines = @asgn_tokens.map { |t| t.pos.line }
42
35
  # Don't attempt to correct the same = more than once
43
36
  @corrected = Set.new
@@ -51,7 +44,7 @@ module RuboCop
51
44
  def autocorrect(range)
52
45
  lambda do |corrector|
53
46
  if range.source.end_with?('=')
54
- align_equal_sign(range, corrector)
47
+ align_equal_signs(range, corrector)
55
48
  else
56
49
  corrector.remove(range)
57
50
  end
@@ -60,6 +53,17 @@ module RuboCop
60
53
 
61
54
  private
62
55
 
56
+ def assignment_tokens
57
+ tokens = processed_source.tokens.select { |t| equal_sign?(t) }
58
+ # we don't want to operate on equals signs which are part of an
59
+ # optarg in a method definition
60
+ # e.g.: def method(optarg = default_val); end
61
+ tokens = remove_optarg_equals(tokens, processed_source)
62
+
63
+ # Only attempt to align the first = on each line
64
+ Set.new(tokens.uniq { |t| t.pos.line })
65
+ end
66
+
63
67
  def check_tokens(ast, t1, t2)
64
68
  return if t2.type == :tNL
65
69
 
@@ -100,20 +104,24 @@ module RuboCop
100
104
  end
101
105
 
102
106
  def check_other(t1, t2, ast)
107
+ extra_space_range(t1, t2) do |range|
108
+ # Unary + doesn't appear as a token and needs special handling.
109
+ next if ignored_range?(ast, range.begin_pos)
110
+ next if unary_plus_non_offense?(range)
111
+
112
+ add_offense(range, range, MSG_UNNECESSARY)
113
+ end
114
+ end
115
+
116
+ def extra_space_range(t1, t2)
103
117
  return if t1.pos.line != t2.pos.line
104
118
  return if allow_for_alignment? && aligned_tok?(t2)
105
119
 
106
120
  start_pos = t1.pos.end_pos
107
121
  end_pos = t2.pos.begin_pos - 1
108
122
  return if end_pos <= start_pos
109
- return if ignored_range?(ast, start_pos)
110
-
111
- range = Parser::Source::Range.new(processed_source.buffer,
112
- start_pos, end_pos)
113
- # Unary + doesn't appear as a token and needs special handling.
114
- return if unary_plus_non_offense?(range)
115
123
 
116
- add_offense(range, range, MSG_UNNECESSARY)
124
+ yield range_between(start_pos, end_pos)
117
125
  end
118
126
 
119
127
  def aligned_tok?(token)
@@ -172,22 +180,25 @@ module RuboCop
172
180
  token.type == :tEQL || token.type == :tOP_ASGN
173
181
  end
174
182
 
175
- def align_equal_sign(range, corrector)
183
+ def align_equal_signs(range, corrector)
176
184
  lines = contiguous_assignment_lines(range)
177
185
  tokens = @asgn_tokens.select { |t| lines.include?(t.pos.line) }
178
186
 
179
187
  columns = tokens.map { |t| align_column(t) }
180
188
  align_to = columns.max
181
189
 
182
- tokens.each do |token|
183
- next unless @corrected.add?(token)
184
- diff = align_to - token.pos.last_column
190
+ tokens.each { |token| align_equal_sign(corrector, token, align_to) }
191
+ end
192
+
193
+ def align_equal_sign(corrector, token, align_to)
194
+ return unless @corrected.add?(token)
185
195
 
186
- if diff > 0
187
- corrector.insert_before(token.pos, ' ' * diff)
188
- elsif diff < 0
189
- corrector.remove_preceding(token.pos, -diff)
190
- end
196
+ diff = align_to - token.pos.last_column
197
+
198
+ if diff > 0
199
+ corrector.insert_before(token.pos, ' ' * diff)
200
+ elsif diff < 0
201
+ corrector.remove_preceding(token.pos, -diff)
191
202
  end
192
203
  end
193
204
 
@@ -97,16 +97,7 @@ module RuboCop
97
97
  end
98
98
 
99
99
  def match_namespace(node, namespace, expected)
100
- expected = expected.dup
101
-
102
- match_partial = lambda do |ns|
103
- next if ns.nil?
104
- while ns
105
- return expected.empty? || expected == [:Object] if ns.cbase_type?
106
- ns, name = *ns
107
- name == expected.last ? expected.pop : (return false)
108
- end
109
- end
100
+ match_partial = partial_matcher!(expected)
110
101
 
111
102
  match_partial.call(namespace)
112
103
 
@@ -115,6 +106,24 @@ module RuboCop
115
106
  match_partial.call(ancestor.defined_module)
116
107
  end
117
108
 
109
+ match?(expected)
110
+ end
111
+
112
+ def partial_matcher!(expected)
113
+ lambda do |namespace|
114
+ while namespace
115
+ return match?(expected) if namespace.cbase_type?
116
+
117
+ namespace, name = *namespace
118
+
119
+ expected.pop if name == expected.last
120
+ end
121
+
122
+ false
123
+ end
124
+ end
125
+
126
+ def match?(expected)
118
127
  expected.empty? || expected == [:Object]
119
128
  end
120
129
 
@@ -74,9 +74,8 @@ module RuboCop
74
74
  end
75
75
 
76
76
  def base_range(send_node, arg_node)
77
- Parser::Source::Range.new(processed_source.buffer,
78
- send_node.source_range.begin_pos,
79
- arg_node.source_range.begin_pos)
77
+ range_between(send_node.source_range.begin_pos,
78
+ arg_node.source_range.begin_pos)
80
79
  end
81
80
 
82
81
  # Returns the column of the given range. For single line ranges, this
@@ -26,23 +26,27 @@ module RuboCop
26
26
  return if block_length(node).zero?
27
27
 
28
28
  method, _args, _body = *node
29
- return unless method.type == :send
29
+ return unless method.send_type?
30
30
 
31
31
  _receiver, method_name, *args = *method
32
32
  return unless method_name == :each && args.empty?
33
33
 
34
34
  if style == :for
35
- end_pos = method.source_range.end_pos
36
- range = Parser::Source::Range.new(processed_source.buffer,
37
- end_pos - EACH_LENGTH,
38
- end_pos)
39
- add_offense(range, range, 'Prefer `for` over `each`.') do
40
- opposite_style_detected
41
- end
35
+ incorrect_style_detected(method)
42
36
  else
43
37
  correct_style_detected
44
38
  end
45
39
  end
40
+
41
+ private
42
+
43
+ def incorrect_style_detected(method)
44
+ end_pos = method.source_range.end_pos
45
+ range = range_between(end_pos - EACH_LENGTH, end_pos)
46
+ add_offense(range, range, 'Prefer `for` over `each`.') do
47
+ opposite_style_detected
48
+ end
49
+ end
46
50
  end
47
51
  end
48
52
  end
@@ -54,7 +54,7 @@ module RuboCop
54
54
 
55
55
  method_name == :% &&
56
56
  ([:str, :dstr].include?(receiver_node.type) ||
57
- arg_nodes[0].type == :array)
57
+ arg_nodes.first.array_type?)
58
58
  end
59
59
 
60
60
  def message(node)
@@ -37,94 +37,60 @@ module RuboCop
37
37
  # raise 'exception' if something
38
38
  # ok
39
39
  class GuardClause < Cop
40
- include ConfigurableEnforcedStyle
41
40
  include IfNode
42
41
  include MinBodyLength
43
42
 
44
43
  MSG = 'Use a guard clause instead of wrapping the code inside a ' \
45
44
  'conditional expression.'.freeze
46
45
 
47
- def_node_matcher :single_line_control_flow_exit?, <<-PATTERN
48
- [{(send nil {:raise :fail} ...) return break next} single_line?]
49
- PATTERN
50
-
51
46
  def on_def(node)
52
47
  _, _, body = *node
48
+
53
49
  return unless body
54
50
 
55
- if if?(body)
56
- check_trailing_if(body)
51
+ if body.if_type?
52
+ check_ending_if(body)
57
53
  elsif body.begin_type?
58
- last_expr = body.children.last
59
- check_trailing_if(last_expr) if if?(last_expr)
54
+ check_ending_if(body.children.last)
60
55
  end
61
56
  end
62
57
 
63
58
  def on_if(node)
64
- return if accept_form?(node)
65
- return unless any_single_line_control_flow_exit?(node)
66
- return if line_too_long_when_corrected?(node)
59
+ return if accepted_form?(node) || !contains_guard_clause?(node)
67
60
 
68
61
  add_offense(node, :keyword, MSG)
69
62
  end
70
63
 
71
64
  private
72
65
 
73
- def accept_form?(node)
74
- cond, body, else_body = *node
75
- return true unless body && else_body
76
- return true if modifier_if?(node) || ternary?(node) || elsif?(node)
77
-
78
- cond.multiline?
79
- end
80
-
81
- def any_single_line_control_flow_exit?(node)
82
- _cond, body, else_body = *node
83
-
84
- single_line_control_flow_exit?(body) ||
85
- single_line_control_flow_exit?(else_body)
86
- end
66
+ def check_ending_if(node)
67
+ return if !node.if_type? ||
68
+ accepted_form?(node, true) ||
69
+ !min_body_length?(node)
87
70
 
88
- def if?(node)
89
- node && node.if_type?
90
- end
91
-
92
- def elsif?(node)
93
- return false unless node.parent && node.parent.if_type?
94
- _condition, _if_branch, else_branch = *node.parent
95
- else_branch.equal?(node)
71
+ add_offense(node, :keyword, MSG)
96
72
  end
97
73
 
98
- def check_trailing_if(node)
99
- cond, body, else_body = *node
74
+ def accepted_form?(node, ending = false)
75
+ condition, = *node
100
76
 
101
- return if body && else_body
102
- # discard modifier ifs and ternary_ops
103
- return if modifier_if?(node) || ternary?(node)
104
- return if cond.multiline?
105
- # discard short ifs
106
- return unless min_body_length?(node)
107
- return if line_too_long_when_corrected?(node)
108
-
109
- add_offense(node, :keyword, MSG)
77
+ ignored_node?(node, ending) || condition.multiline?
110
78
  end
111
79
 
112
- def line_too_long_when_corrected?(node)
113
- cond, body, else_body = *node
80
+ def ignored_node?(node, ending)
81
+ return true if modifier_if?(node) || ternary?(node)
114
82
 
115
- if single_line_control_flow_exit?(body) || !else_body
116
- line_too_long?(node, body, 'if', cond)
83
+ if ending
84
+ if_else?(node)
117
85
  else
118
- line_too_long?(node, else_body, 'unless', cond)
86
+ !if_else?(node) || elsif?(node)
119
87
  end
120
88
  end
121
89
 
122
- def line_too_long?(node, body, keyword, condition)
123
- max = config.for_cop('Metrics/LineLength')['Max'] || 80
124
- indent = node.loc.column
125
- source = body && body.source || ''
126
- # 2 is for spaces on left and right of keyword
127
- indent + (source + keyword + condition.source).length + 2 > max
90
+ def contains_guard_clause?(node)
91
+ _, body, else_body = *node
92
+
93
+ guard_clause?(body) || guard_clause?(else_body)
128
94
  end
129
95
  end
130
96
  end
@@ -10,11 +10,64 @@ module RuboCop
10
10
  # the use of the newer Ruby 1.9 syntax (when applicable).
11
11
  #
12
12
  # A separate offense is registered for each problematic pair.
13
+ #
14
+ # The supported styles are:
15
+ #
16
+ # * ruby19 - forces use of the 1.9 syntax (e.g. {a: 1}) when hashes have
17
+ # all symbols for keys
18
+ # * hash_rockets - forces use of hash rockets for all hashes
19
+ # * no_mixed_keys - simply checks for hashes with mixed syntaxes
20
+ # * ruby19_mixed_keys - forces use of ruby 1.9 syntax and forbids mixed
21
+ # syntax hashes
22
+ #
23
+ # @example
24
+ # "EnforcedStyle => 'ruby19'"
25
+ #
26
+ # @good
27
+ # {a: 2, b: 1}
28
+ # {:c => 2, 'd' => 2} # acceptable since 'd' isn't a symbol
29
+ # {d: 1, 'e' => 2} # technically not forbidden
30
+ #
31
+ # @bad
32
+ # {:a => 2}
33
+ # {b: 1, :c => 2}
34
+ #
35
+ # @example
36
+ # "EnforcedStyle => 'hash_rockets'"
37
+ #
38
+ # @good
39
+ # {:a => 1, :b => 2}
40
+ #
41
+ # @bad
42
+ # {a: 1, b: 2}
43
+ # {c: 1, 'd' => 5}
44
+ #
45
+ # @example
46
+ # "EnforcedStyle => 'no_mixed_keys'"
47
+ #
48
+ # @good
49
+ # {:a => 1, :b => 2}
50
+ # {c: 1, d: 2}
51
+ #
52
+ # @bad
53
+ # {:a => 1, b: 2}
54
+ # {c: 1, 'd' => 2}
55
+ #
56
+ # @example
57
+ # "EnforcedStyle => 'ruby19_no_mixed_keys'"
58
+ #
59
+ # @good
60
+ # {a: 1, b: 2}
61
+ # {:c => 3, 'd' => 4}
62
+ #
63
+ # @bad
64
+ # {:a => 1, :b => 2}
65
+ # {c: 2, 'd' => 3} # should just use hash rockets
13
66
  class HashSyntax < Cop
14
67
  include ConfigurableEnforcedStyle
15
68
 
16
69
  MSG_19 = 'Use the new Ruby 1.9 hash syntax.'.freeze
17
- MSG_RUBY19_NO_MIXED_KEYS = "Don't mix styles in the same hash.".freeze
70
+ MSG_NO_MIXED_KEYS = "Don't mix styles in the same hash.".freeze
18
71
  MSG_HASH_ROCKETS = 'Use hash rockets syntax.'.freeze
19
72
 
20
73
  @force_hash_rockets = false
@@ -29,6 +82,8 @@ module RuboCop
29
82
  hash_rockets_check(node)
30
83
  elsif style == :ruby19_no_mixed_keys
31
84
  ruby19_no_mixed_keys_check(node)
85
+ elsif style == :no_mixed_keys
86
+ no_mixed_keys_check(node)
32
87
  else
33
88
  ruby19_check(node)
34
89
  end
@@ -54,7 +109,18 @@ module RuboCop
54
109
  elsif sym_indices?(pairs)
55
110
  check(pairs, '=>', MSG_19)
56
111
  else
57
- check(pairs, ':', MSG_RUBY19_NO_MIXED_KEYS)
112
+ check(pairs, ':', MSG_NO_MIXED_KEYS)
113
+ end
114
+ end
115
+
116
+ def no_mixed_keys_check(node)
117
+ pairs = *node
118
+
119
+ if !sym_indices?(pairs)
120
+ check(pairs, ':', MSG_NO_MIXED_KEYS)
121
+ else
122
+ delim = pairs.first.loc.operator.source == ':' ? '=>' : ':'
123
+ check(pairs, delim, MSG_NO_MIXED_KEYS)
58
124
  end
59
125
  end
60
126
 
@@ -62,8 +128,8 @@ module RuboCop
62
128
  lambda do |corrector|
63
129
  if style == :hash_rockets || @force_hash_rockets
64
130
  autocorrect_hash_rockets(corrector, node)
65
- elsif style == :ruby19_no_mixed_keys
66
- autocorrect_ruby19_no_mixed_keys(corrector, node)
131
+ elsif style == :ruby19_no_mixed_keys || style == :no_mixed_keys
132
+ autocorrect_no_mixed_keys(corrector, node)
67
133
  else
68
134
  autocorrect_ruby19(corrector, node)
69
135
  end
@@ -134,8 +200,7 @@ module RuboCop
134
200
  key = node.children.first.source_range
135
201
  op = node.loc.operator
136
202
 
137
- range = Parser::Source::Range.new(key.source_buffer,
138
- key.begin_pos, op.end_pos)
203
+ range = range_between(key.begin_pos, op.end_pos)
139
204
  range = range_with_surrounding_space(range, :right)
140
205
  corrector.replace(range,
141
206
  range.source.sub(/^:(.*\S)\s*=>\s*$/, '\1: '))
@@ -150,7 +215,7 @@ module RuboCop
150
215
  corrector.remove(range_with_surrounding_space(op))
151
216
  end
152
217
 
153
- def autocorrect_ruby19_no_mixed_keys(corrector, node)
218
+ def autocorrect_no_mixed_keys(corrector, node)
154
219
  op = node.loc.operator
155
220
 
156
221
  if op.is?(':')