rubocop 0.46.0 → 0.47.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 (214) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +77 -2
  4. data/config/default.yml +151 -74
  5. data/config/disabled.yml +9 -0
  6. data/config/enabled.yml +49 -9
  7. data/lib/rubocop.rb +36 -8
  8. data/lib/rubocop/ast/builder.rb +59 -0
  9. data/lib/rubocop/ast/node.rb +607 -0
  10. data/lib/rubocop/ast/node/array_node.rb +45 -0
  11. data/lib/rubocop/ast/node/case_node.rb +63 -0
  12. data/lib/rubocop/ast/node/for_node.rb +53 -0
  13. data/lib/rubocop/ast/node/hash_node.rb +102 -0
  14. data/lib/rubocop/ast/node/if_node.rb +136 -0
  15. data/lib/rubocop/ast/node/keyword_splat_node.rb +45 -0
  16. data/lib/rubocop/ast/node/mixin/conditional_node.rb +45 -0
  17. data/lib/rubocop/ast/node/mixin/hash_element_node.rb +125 -0
  18. data/lib/rubocop/ast/node/mixin/modifier_node.rb +17 -0
  19. data/lib/rubocop/ast/node/pair_node.rb +64 -0
  20. data/lib/rubocop/ast/node/until_node.rb +43 -0
  21. data/lib/rubocop/ast/node/when_node.rb +61 -0
  22. data/lib/rubocop/ast/node/while_node.rb +43 -0
  23. data/lib/rubocop/ast/sexp.rb +16 -0
  24. data/lib/rubocop/{ast_node → ast}/traversal.rb +1 -1
  25. data/lib/rubocop/cli.rb +18 -14
  26. data/lib/rubocop/comment_config.rb +1 -3
  27. data/lib/rubocop/config.rb +93 -35
  28. data/lib/rubocop/config_loader.rb +1 -1
  29. data/lib/rubocop/cop/badge.rb +73 -0
  30. data/lib/rubocop/cop/bundler/duplicated_gem.rb +2 -2
  31. data/lib/rubocop/cop/bundler/ordered_gems.rb +43 -3
  32. data/lib/rubocop/cop/commissioner.rb +17 -6
  33. data/lib/rubocop/cop/cop.rb +25 -112
  34. data/lib/rubocop/cop/lint/ambiguous_operator.rb +9 -4
  35. data/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb +7 -0
  36. data/lib/rubocop/cop/lint/assignment_in_condition.rb +18 -4
  37. data/lib/rubocop/cop/lint/block_alignment.rb +40 -9
  38. data/lib/rubocop/cop/lint/circular_argument_reference.rb +14 -0
  39. data/lib/rubocop/cop/lint/condition_position.rb +14 -16
  40. data/lib/rubocop/cop/lint/debugger.rb +28 -0
  41. data/lib/rubocop/cop/lint/def_end_alignment.rb +21 -1
  42. data/lib/rubocop/cop/lint/deprecated_class_methods.rb +13 -1
  43. data/lib/rubocop/cop/lint/duplicate_case_condition.rb +26 -22
  44. data/lib/rubocop/cop/lint/duplicate_methods.rb +15 -1
  45. data/lib/rubocop/cop/lint/duplicated_key.rb +16 -8
  46. data/lib/rubocop/cop/lint/each_with_object_argument.rb +9 -0
  47. data/lib/rubocop/cop/lint/else_layout.rb +26 -29
  48. data/lib/rubocop/cop/lint/empty_ensure.rb +38 -0
  49. data/lib/rubocop/cop/lint/empty_expression.rb +11 -1
  50. data/lib/rubocop/cop/lint/empty_interpolation.rb +8 -0
  51. data/lib/rubocop/cop/lint/empty_when.rb +14 -16
  52. data/lib/rubocop/cop/lint/end_alignment.rb +48 -28
  53. data/lib/rubocop/cop/lint/end_in_method.rb +23 -0
  54. data/lib/rubocop/cop/lint/ensure_return.rb +21 -0
  55. data/lib/rubocop/cop/lint/float_out_of_range.rb +5 -0
  56. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +29 -4
  57. data/lib/rubocop/cop/lint/handle_exceptions.rb +40 -0
  58. data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +7 -2
  59. data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +11 -2
  60. data/lib/rubocop/cop/lint/invalid_character_literal.rb +3 -0
  61. data/lib/rubocop/cop/lint/literal_in_condition.rb +34 -36
  62. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +8 -0
  63. data/lib/rubocop/cop/lint/loop.rb +36 -0
  64. data/lib/rubocop/cop/lint/multiple_compare.rb +46 -0
  65. data/lib/rubocop/cop/lint/nested_method_definition.rb +22 -0
  66. data/lib/rubocop/cop/lint/next_without_accumulator.rb +5 -0
  67. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +8 -0
  68. data/lib/rubocop/cop/lint/percent_string_array.rb +27 -13
  69. data/lib/rubocop/cop/lint/percent_symbol_array.rb +14 -4
  70. data/lib/rubocop/cop/lint/rand_one.rb +7 -3
  71. data/lib/rubocop/cop/lint/require_parentheses.rb +20 -19
  72. data/lib/rubocop/cop/lint/rescue_exception.rb +20 -0
  73. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +66 -0
  74. data/lib/rubocop/cop/lint/shadowed_exception.rb +6 -1
  75. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +24 -0
  76. data/lib/rubocop/cop/lint/string_conversion_in_interpolation.rb +8 -0
  77. data/lib/rubocop/cop/lint/underscore_prefixed_variable_name.rb +24 -0
  78. data/lib/rubocop/cop/lint/unified_integer.rb +5 -0
  79. data/lib/rubocop/cop/lint/unneeded_disable.rb +2 -2
  80. data/lib/rubocop/cop/lint/unneeded_splat_expansion.rb +5 -0
  81. data/lib/rubocop/cop/lint/unreachable_code.rb +17 -0
  82. data/lib/rubocop/cop/lint/unused_block_argument.rb +2 -0
  83. data/lib/rubocop/cop/lint/unused_method_argument.rb +10 -0
  84. data/lib/rubocop/cop/lint/useless_access_modifier.rb +28 -1
  85. data/lib/rubocop/cop/lint/useless_assignment.rb +18 -0
  86. data/lib/rubocop/cop/lint/useless_comparison.rb +3 -1
  87. data/lib/rubocop/cop/lint/useless_else_without_rescue.rb +16 -1
  88. data/lib/rubocop/cop/lint/useless_setter_call.rb +16 -4
  89. data/lib/rubocop/cop/lint/void.rb +52 -0
  90. data/lib/rubocop/cop/message_annotator.rb +102 -0
  91. data/lib/rubocop/cop/metrics/block_length.rb +6 -0
  92. data/lib/rubocop/cop/metrics/block_nesting.rb +17 -5
  93. data/lib/rubocop/cop/metrics/line_length.rb +11 -4
  94. data/lib/rubocop/cop/metrics/perceived_complexity.rb +1 -2
  95. data/lib/rubocop/cop/mixin/array_syntax.rb +2 -11
  96. data/lib/rubocop/cop/mixin/configurable_enforced_style.rb +12 -5
  97. data/lib/rubocop/cop/mixin/configurable_formatting.rb +48 -0
  98. data/lib/rubocop/cop/mixin/configurable_max.rb +3 -3
  99. data/lib/rubocop/cop/mixin/configurable_naming.rb +5 -33
  100. data/lib/rubocop/cop/mixin/configurable_numbering.rb +6 -47
  101. data/lib/rubocop/cop/mixin/documentation_comment.rb +7 -1
  102. data/lib/rubocop/cop/mixin/duplication.rb +46 -0
  103. data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +2 -2
  104. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +14 -11
  105. data/lib/rubocop/cop/mixin/hash_alignment.rb +114 -0
  106. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +3 -3
  107. data/lib/rubocop/cop/mixin/negative_conditional.rb +21 -7
  108. data/lib/rubocop/cop/mixin/on_method_def.rb +14 -0
  109. data/lib/rubocop/cop/mixin/on_normal_if_unless.rb +1 -24
  110. data/lib/rubocop/cop/mixin/statement_modifier.rb +8 -13
  111. data/lib/rubocop/cop/mixin/target_ruby_version.rb +16 -0
  112. data/lib/rubocop/cop/mixin/trailing_comma.rb +2 -3
  113. data/lib/rubocop/cop/offense.rb +1 -1
  114. data/lib/rubocop/cop/performance/case_when_splat.rb +56 -59
  115. data/lib/rubocop/cop/performance/detect.rb +2 -2
  116. data/lib/rubocop/cop/performance/flat_map.rb +3 -3
  117. data/lib/rubocop/cop/performance/redundant_merge.rb +3 -6
  118. data/lib/rubocop/cop/performance/regexp_match.rb +201 -0
  119. data/lib/rubocop/cop/rails/delegate.rb +2 -2
  120. data/lib/rubocop/cop/rails/delegate_allow_blank.rb +10 -19
  121. data/lib/rubocop/cop/rails/enum_uniqueness.rb +12 -40
  122. data/lib/rubocop/cop/rails/file_path.rb +80 -0
  123. data/lib/rubocop/cop/rails/find_each.rb +5 -14
  124. data/lib/rubocop/cop/rails/http_positional_arguments.rb +30 -24
  125. data/lib/rubocop/cop/rails/not_null_column.rb +23 -0
  126. data/lib/rubocop/cop/rails/reversible_migration.rb +217 -0
  127. data/lib/rubocop/cop/rails/safe_navigation.rb +4 -2
  128. data/lib/rubocop/cop/rails/skips_model_validations.rb +46 -0
  129. data/lib/rubocop/cop/rails/time_zone.rb +1 -1
  130. data/lib/rubocop/cop/rails/uniq_before_pluck.rb +7 -5
  131. data/lib/rubocop/cop/registry.rb +170 -0
  132. data/lib/rubocop/cop/{lint → security}/eval.rb +7 -1
  133. data/lib/rubocop/cop/security/marshal_load.rb +33 -0
  134. data/lib/rubocop/cop/security/yaml_load.rb +37 -0
  135. data/lib/rubocop/cop/style/align_hash.rb +138 -169
  136. data/lib/rubocop/cop/style/and_or.rb +1 -1
  137. data/lib/rubocop/cop/style/braces_around_hash_parameters.rb +10 -15
  138. data/lib/rubocop/cop/style/case_indentation.rb +36 -27
  139. data/lib/rubocop/cop/style/conditional_assignment.rb +64 -47
  140. data/lib/rubocop/cop/style/each_with_object.rb +4 -1
  141. data/lib/rubocop/cop/style/else_alignment.rb +14 -20
  142. data/lib/rubocop/cop/style/empty_case_condition.rb +16 -25
  143. data/lib/rubocop/cop/style/empty_else.rb +20 -22
  144. data/lib/rubocop/cop/style/empty_literal.rb +4 -4
  145. data/lib/rubocop/cop/style/empty_method.rb +12 -6
  146. data/lib/rubocop/cop/style/encoding.rb +1 -1
  147. data/lib/rubocop/cop/style/file_name.rb +24 -4
  148. data/lib/rubocop/cop/style/first_method_argument_line_break.rb +1 -1
  149. data/lib/rubocop/cop/style/format_string.rb +17 -48
  150. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +40 -11
  151. data/lib/rubocop/cop/style/guard_clause.rb +11 -17
  152. data/lib/rubocop/cop/style/hash_syntax.rb +24 -42
  153. data/lib/rubocop/cop/style/identical_conditional_branches.rb +40 -28
  154. data/lib/rubocop/cop/style/if_inside_else.rb +6 -9
  155. data/lib/rubocop/cop/style/if_unless_modifier.rb +16 -25
  156. data/lib/rubocop/cop/style/if_unless_modifier_of_if_unless.rb +3 -9
  157. data/lib/rubocop/cop/style/indent_array.rb +1 -1
  158. data/lib/rubocop/cop/style/indentation_width.rb +29 -60
  159. data/lib/rubocop/cop/style/infinite_loop.rb +21 -22
  160. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +86 -0
  161. data/lib/rubocop/cop/style/{method_call_parentheses.rb → method_call_without_args_parentheses.rb} +8 -1
  162. data/lib/rubocop/cop/style/missing_else.rb +40 -14
  163. data/lib/rubocop/cop/style/multiline_if_modifier.rb +5 -15
  164. data/lib/rubocop/cop/style/multiline_if_then.rb +14 -8
  165. data/lib/rubocop/cop/style/multiline_method_call_indentation.rb +3 -3
  166. data/lib/rubocop/cop/style/multiline_ternary_operator.rb +1 -5
  167. data/lib/rubocop/cop/style/mutable_constant.rb +3 -2
  168. data/lib/rubocop/cop/style/negated_if.rb +3 -19
  169. data/lib/rubocop/cop/style/negated_while.rb +2 -17
  170. data/lib/rubocop/cop/style/nested_modifier.rb +16 -43
  171. data/lib/rubocop/cop/style/nested_ternary_operator.rb +3 -5
  172. data/lib/rubocop/cop/style/next.rb +23 -21
  173. data/lib/rubocop/cop/style/non_nil_check.rb +2 -3
  174. data/lib/rubocop/cop/style/not.rb +1 -3
  175. data/lib/rubocop/cop/style/numeric_literals.rb +2 -2
  176. data/lib/rubocop/cop/style/one_line_conditional.rb +12 -22
  177. data/lib/rubocop/cop/style/option_hash.rb +4 -15
  178. data/lib/rubocop/cop/style/parallel_assignment.rb +1 -3
  179. data/lib/rubocop/cop/style/parentheses_around_condition.rb +8 -12
  180. data/lib/rubocop/cop/style/percent_q_literals.rb +15 -12
  181. data/lib/rubocop/cop/style/redundant_freeze.rb +3 -2
  182. data/lib/rubocop/cop/style/redundant_parentheses.rb +27 -4
  183. data/lib/rubocop/cop/style/redundant_return.rb +4 -8
  184. data/lib/rubocop/cop/style/safe_navigation.rb +13 -6
  185. data/lib/rubocop/cop/style/space_after_colon.rb +2 -4
  186. data/lib/rubocop/cop/style/space_around_block_parameters.rb +1 -1
  187. data/lib/rubocop/cop/style/space_around_operators.rb +15 -13
  188. data/lib/rubocop/cop/style/string_methods.rb +1 -3
  189. data/lib/rubocop/cop/style/symbol_array.rb +1 -5
  190. data/lib/rubocop/cop/style/ternary_parentheses.rb +5 -6
  191. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +2 -5
  192. data/lib/rubocop/cop/style/trailing_comma_in_literal.rb +1 -1
  193. data/lib/rubocop/cop/style/unless_else.rb +1 -5
  194. data/lib/rubocop/cop/style/when_then.rb +4 -2
  195. data/lib/rubocop/cop/style/while_until_do.rb +9 -13
  196. data/lib/rubocop/cop/style/while_until_modifier.rb +12 -11
  197. data/lib/rubocop/cop/style/word_array.rb +5 -9
  198. data/lib/rubocop/cop/team.rb +16 -15
  199. data/lib/rubocop/cop/util.rb +13 -3
  200. data/lib/rubocop/formatter/clang_style_formatter.rb +2 -2
  201. data/lib/rubocop/formatter/disabled_config_formatter.rb +2 -1
  202. data/lib/rubocop/magic_comment.rb +196 -0
  203. data/lib/rubocop/options.rb +5 -4
  204. data/lib/rubocop/processed_source.rb +1 -1
  205. data/lib/rubocop/rspec/cop_helper.rb +9 -0
  206. data/lib/rubocop/rspec/shared_examples.rb +1 -1
  207. data/lib/rubocop/runner.rb +7 -2
  208. data/lib/rubocop/version.rb +1 -1
  209. metadata +41 -14
  210. data/lib/rubocop/ast_node.rb +0 -624
  211. data/lib/rubocop/ast_node/builder.rb +0 -30
  212. data/lib/rubocop/ast_node/sexp.rb +0 -13
  213. data/lib/rubocop/cop/mixin/hash_node.rb +0 -14
  214. data/lib/rubocop/cop/mixin/if_node.rb +0 -42
@@ -16,18 +16,18 @@ module RuboCop
16
16
  # work
17
17
  # end
18
18
  class InfiniteLoop < Cop
19
+ LEADING_SPACE = /\A(\s*)/
20
+
19
21
  MSG = 'Use `Kernel#loop` for infinite loops.'.freeze
20
22
 
21
23
  def on_while(node)
22
- condition, = *node
23
- return unless condition.truthy_literal?
24
+ return unless node.condition.truthy_literal?
24
25
 
25
26
  add_offense(node, :keyword)
26
27
  end
27
28
 
28
29
  def on_until(node)
29
- condition, = *node
30
- return unless condition.falsey_literal?
30
+ return unless node.condition.falsey_literal?
31
31
 
32
32
  add_offense(node, :keyword)
33
33
  end
@@ -35,6 +35,8 @@ module RuboCop
35
35
  alias on_while_post on_while
36
36
  alias on_until_post on_until
37
37
 
38
+ private
39
+
38
40
  def autocorrect(node)
39
41
  if node.while_post_type? || node.until_post_type?
40
42
  replace_begin_end_with_modifier(node)
@@ -45,46 +47,43 @@ module RuboCop
45
47
  end
46
48
  end
47
49
 
48
- private
49
-
50
50
  def replace_begin_end_with_modifier(node)
51
- _, body = *node
52
-
53
51
  lambda do |corrector|
54
- corrector.replace(body.loc.begin, 'loop do')
55
- corrector.remove(body.loc.end.end.join(node.source_range.end))
52
+ corrector.replace(node.body.loc.begin, 'loop do')
53
+ corrector.remove(node.body.loc.end.end.join(node.source_range.end))
56
54
  end
57
55
  end
58
56
 
59
57
  def replace_source(range, replacement)
60
- ->(corrector) { corrector.replace(range, replacement) }
58
+ lambda do |corrector|
59
+ corrector.replace(range, replacement)
60
+ end
61
61
  end
62
62
 
63
63
  def modifier_replacement(node)
64
- _, body = *node
65
64
  if node.single_line?
66
- 'loop { ' + body.source + ' }'
65
+ 'loop { ' + node.body.source + ' }'
67
66
  else
68
- indentation = body.loc.expression.source_line[/\A(\s*)/]
69
- "loop do\n" + indentation +
70
- body.source.gsub(/^/, ' ' * configured_indentation_width) +
71
- "\n#{indentation}end"
67
+ indentation = node.body.loc.expression.source_line[LEADING_SPACE]
68
+
69
+ ['loop do', node.body.source.gsub(/^/, configured_indent),
70
+ 'end'].join("\n#{indentation}")
72
71
  end
73
72
  end
74
73
 
75
74
  def non_modifier_range(node)
76
- condition_node, = *node
77
75
  start_range = node.loc.keyword.begin
78
- end_range = if node.loc.begin
76
+ end_range = if node.do?
79
77
  node.loc.begin.end
80
78
  else
81
- condition_node.source_range.end
79
+ node.condition.source_range.end
82
80
  end
81
+
83
82
  start_range.join(end_range)
84
83
  end
85
84
 
86
- def configured_indentation_width
87
- config.for_cop('IndentationWidth')['Width']
85
+ def configured_indent
86
+ ' ' * config.for_cop('IndentationWidth')['Width']
88
87
  end
89
88
  end
90
89
  end
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Style
6
+ # This cop checks presence of parentheses in method calls containing
7
+ # parameters.
8
+ # As in popular Ruby's frameworks a lot of methods should always be
9
+ # called without parentheses,
10
+ # users can ignore them by passing their names to IgnoredMethods option.
11
+ #
12
+ # @example
13
+ # # bad
14
+ # array.delete e
15
+ #
16
+ # # good
17
+ # array.delete(e)
18
+ #
19
+ # # good if `puts` is listed in IgnoredMethods
20
+ # puts 'test'
21
+ class MethodCallWithArgsParentheses < Cop
22
+ MSG = 'Use parentheses for method calls with arguments.'.freeze
23
+
24
+ def on_send(node)
25
+ _receiver, method_name, *args = *node
26
+ return if ignored_list.include?(method_name)
27
+ return if args.empty?
28
+ return if operator_call?(node)
29
+ return if parentheses?(node)
30
+
31
+ add_offense(node, :selector)
32
+ end
33
+
34
+ def on_super(node)
35
+ # super nodetype implies call with arguments.
36
+ return if parentheses?(node)
37
+
38
+ add_offense(node, :keyword)
39
+ end
40
+
41
+ def on_yield(node)
42
+ args = node.children
43
+ return if args.empty?
44
+ return if parentheses?(node)
45
+
46
+ add_offense(node, :keyword)
47
+ end
48
+
49
+ def autocorrect(node)
50
+ lambda do |corrector|
51
+ corrector.replace(args_begin(node), '(')
52
+ corrector.insert_after(args_end(node), ')')
53
+ end
54
+ end
55
+
56
+ private
57
+
58
+ def ignored_list
59
+ cop_config['IgnoredMethods'].map(&:to_sym)
60
+ end
61
+
62
+ def parentheses?(node)
63
+ node.loc.begin
64
+ end
65
+
66
+ def operator_call?(node)
67
+ node.loc.operator || (reciever?(node) && !node.loc.dot)
68
+ end
69
+
70
+ def reciever?(node)
71
+ !node.children[0].nil?
72
+ end
73
+
74
+ def args_begin(node)
75
+ loc = node.loc
76
+ selector = node.super_type? ? loc.keyword : loc.selector
77
+ selector.end.resize(1)
78
+ end
79
+
80
+ def args_end(node)
81
+ node.loc.expression.end
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
@@ -4,7 +4,14 @@ module RuboCop
4
4
  module Cop
5
5
  module Style
6
6
  # This cop checks for unwanted parentheses in parameterless method calls.
7
- class MethodCallParentheses < Cop
7
+ #
8
+ # @example
9
+ # # bad
10
+ # object.some_method()
11
+ #
12
+ # # good
13
+ # object.some_method
14
+ class MethodCallWithoutArgsParentheses < Cop
8
15
  MSG = 'Do not use parentheses for method calls with ' \
9
16
  'no arguments.'.freeze
10
17
 
@@ -38,35 +38,61 @@ module RuboCop
38
38
  MSG_EMPTY = '`%s` condition requires an empty `else`-clause.'.freeze
39
39
 
40
40
  def on_normal_if_unless(node)
41
- unless_else_cop = config.for_cop('Style/UnlessElse')
42
- unless_else_enabled = unless_else_cop['Enabled'] if unless_else_cop
43
- return if unless_else_enabled &&
44
- node.loc.keyword &&
45
- node.loc.keyword.is?('unless')
46
- check(node, if_else_clause(node)) unless style == :case
41
+ return if case_style?
42
+ return if unless_else_cop_enabled? && node.unless?
43
+
44
+ check(node)
47
45
  end
48
46
 
49
47
  def on_case(node)
50
- check(node, case_else_clause(node)) unless style == :if
48
+ return if if_style?
49
+
50
+ check(node)
51
51
  end
52
52
 
53
53
  private
54
54
 
55
- def check(node, _else_clause)
56
- return if node.loc.else
57
- empty_else = config.for_cop('Style/EmptyElse')
55
+ def check(node)
56
+ return if node.else?
58
57
 
59
- if empty_else && empty_else['Enabled']
60
- case empty_else['EnforcedStyle']
61
- when 'empty'
58
+ if empty_else_cop_enabled?
59
+ if empty_else_style == :empty
62
60
  add_offense(node, :expression, format(MSG_NIL, node.type))
63
- when 'nil'
61
+ elsif empty_else_style == :nil
64
62
  add_offense(node, :expression, format(MSG_EMPTY, node.type))
65
63
  end
66
64
  end
67
65
 
68
66
  add_offense(node, :expression, format(MSG, node.type))
69
67
  end
68
+
69
+ def if_style?
70
+ style == :if
71
+ end
72
+
73
+ def case_style?
74
+ style == :case
75
+ end
76
+
77
+ def unless_else_cop_enabled?
78
+ unless_else_config['Enabled'] if unless_else_config
79
+ end
80
+
81
+ def unless_else_config
82
+ config.for_cop('Style/UnlessElse')
83
+ end
84
+
85
+ def empty_else_cop_enabled?
86
+ empty_else_config['Enabled'] if empty_else_config
87
+ end
88
+
89
+ def empty_else_style
90
+ empty_else_config['EnforcedStyle'].to_sym if empty_else_config
91
+ end
92
+
93
+ def empty_else_config
94
+ config.for_cop('Style/EmptyElse')
95
+ end
70
96
  end
71
97
  end
72
98
  end
@@ -15,7 +15,6 @@ module RuboCop
15
15
  # # good
16
16
  # { result: 'ok' } if cond
17
17
  class MultilineIfModifier < Cop
18
- include IfNode
19
18
  include StatementModifier
20
19
  include AutocorrectAlignment
21
20
 
@@ -23,20 +22,13 @@ module RuboCop
23
22
  ' clause in a multiline statement.'.freeze
24
23
 
25
24
  def on_if(node)
26
- return unless modifier_if?(node)
25
+ return unless node.modifier_form? && node.body.multiline?
27
26
 
28
- _cond, body = if_node_parts(node)
29
- return if body.single_line?
30
-
31
- add_offense(node, :expression)
27
+ add_offense(node, :expression, format(MSG, node.keyword))
32
28
  end
33
29
 
34
30
  private
35
31
 
36
- def message(node)
37
- format(MSG, node.loc.keyword.source)
38
- end
39
-
40
32
  def autocorrect(node)
41
33
  lambda do |corrector|
42
34
  corrector.replace(node.source_range, to_normal_if(node))
@@ -44,13 +36,11 @@ module RuboCop
44
36
  end
45
37
 
46
38
  def to_normal_if(node)
47
- cond, body = if_node_parts(node)
48
- indented_body = indented_body(body, node)
49
-
50
- condition = "#{node.loc.keyword.source} #{cond.source}"
39
+ indented_body = indented_body(node.body, node)
40
+ condition = "#{node.keyword} #{node.condition.source}"
51
41
  indented_end = "#{offset(node)}end"
52
42
 
53
- "#{condition}\n#{indented_body}\n#{indented_end}"
43
+ [condition, indented_body, indented_end].join("\n")
54
44
  end
55
45
 
56
46
  def configured_indentation_width
@@ -16,23 +16,29 @@ module RuboCop
16
16
  # elsif cond then b
17
17
  # end
18
18
  class MultilineIfThen < Cop
19
- include IfNode
20
19
  include OnNormalIfUnless
21
20
 
21
+ NON_MODIFIER_THEN = /then\s*(#.*)?$/
22
+
23
+ MSG = 'Do not use `then` for multi-line `%s`.'.freeze
24
+
22
25
  def on_normal_if_unless(node)
23
- return unless node.loc.begin
24
- return unless node.loc.begin.source_line =~ /then\s*(#.*)?$/
25
- add_offense(node, :begin)
26
+ return unless non_modifier_then?(node)
27
+
28
+ add_offense(node, :begin, format(MSG, node.keyword))
26
29
  end
27
30
 
28
- def message(node)
29
- "Do not use `then` for multi-line `#{node.loc.keyword.source}`."
31
+ private
32
+
33
+ def non_modifier_then?(node)
34
+ node.loc.begin && node.loc.begin.source_line =~ NON_MODIFIER_THEN
30
35
  end
31
36
 
32
37
  def autocorrect(node)
33
38
  lambda do |corrector|
34
- corrector.remove(range_with_surrounding_space(node.loc.begin,
35
- :left))
39
+ corrector.remove(
40
+ range_with_surrounding_space(node.loc.begin, :left)
41
+ )
36
42
  end
37
43
  end
38
44
  end
@@ -129,9 +129,9 @@ module RuboCop
129
129
  n = kw_node_with_special_indentation(lhs)
130
130
  if n
131
131
  case n.type
132
- when :if, :while, :until then expression, = *n
133
- when :for then _, expression, = *n
134
- when :return then expression, = *n
132
+ when :for then _, expression, = *n
133
+ when :return then expression, = *n
134
+ when *MODIFIER_NODES then expression, = *n
135
135
  end
136
136
  return expression.source_range
137
137
  end
@@ -5,15 +5,11 @@ module RuboCop
5
5
  module Style
6
6
  # This cop checks for multi-line ternary op expressions.
7
7
  class MultilineTernaryOperator < Cop
8
- include IfNode
9
-
10
8
  MSG = 'Avoid multi-line ternary operators, ' \
11
9
  'use `if` or `unless` instead.'.freeze
12
10
 
13
11
  def on_if(node)
14
- _condition, _if_branch, = *node
15
-
16
- return unless ternary?(node) && node.multiline?
12
+ return unless node.ternary? && node.multiline?
17
13
 
18
14
  add_offense(node, :expression)
19
15
  end
@@ -37,15 +37,16 @@ module RuboCop
37
37
 
38
38
  return unless value && value.mutable_literal?
39
39
  return if FROZEN_STRING_LITERAL_TYPES.include?(value.type) &&
40
- frozen_string_literals_enabled?(processed_source)
40
+ frozen_string_literals_enabled?
41
41
 
42
42
  add_offense(value, :expression)
43
43
  end
44
44
 
45
45
  def autocorrect(node)
46
46
  expr = node.source_range
47
+
47
48
  lambda do |corrector|
48
- if node.array_type? && node.loc.begin.nil? && node.loc.end.nil?
49
+ if node.array_type? && !node.square_brackets?
49
50
  corrector.insert_before(expr, '[')
50
51
  corrector.insert_after(expr, '].freeze')
51
52
  else
@@ -11,35 +11,19 @@ module RuboCop
11
11
  MSG = 'Favor `%s` over `%s` for negative conditions.'.freeze
12
12
 
13
13
  def on_if(node)
14
- return unless node.loc.respond_to?(:keyword)
15
- return if node.loc.keyword.is?('elsif')
14
+ return if node.elsif?
16
15
 
17
16
  check_negative_conditional(node)
18
17
  end
19
18
 
20
19
  def message(node)
21
- if node.loc.keyword.is?('if')
22
- format(MSG, 'unless', 'if')
23
- else
24
- format(MSG, 'if', 'unless')
25
- end
20
+ format(MSG, node.inverse_keyword, node.keyword)
26
21
  end
27
22
 
28
23
  private
29
24
 
30
25
  def autocorrect(node)
31
- lambda do |corrector|
32
- condition, _body, _rest = *node
33
- # look inside parentheses around the condition
34
- condition = condition.children.first while condition.begin_type?
35
- # unwrap the negated portion of the condition (a send node)
36
- pos_condition, _method, = *condition
37
- corrector.replace(
38
- node.loc.keyword,
39
- node.loc.keyword.is?('if') ? 'unless' : 'if'
40
- )
41
- corrector.replace(condition.source_range, pos_condition.source)
42
- end
26
+ negative_conditional_corrector(node)
43
27
  end
44
28
  end
45
29
  end