rubocop 0.19.1 → 0.20.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 (192) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +4 -0
  3. data/CHANGELOG.md +60 -1
  4. data/CONTRIBUTING.md +2 -1
  5. data/README.md +9 -7
  6. data/config/default.yml +3 -3
  7. data/config/disabled.yml +4 -0
  8. data/config/enabled.yml +45 -21
  9. data/lib/rubocop.rb +30 -9
  10. data/lib/rubocop/cli.rb +1 -1
  11. data/lib/rubocop/comment_config.rb +4 -2
  12. data/lib/rubocop/config.rb +16 -22
  13. data/lib/rubocop/config_loader.rb +29 -26
  14. data/lib/rubocop/cop/commissioner.rb +1 -1
  15. data/lib/rubocop/cop/cop.rb +6 -6
  16. data/lib/rubocop/cop/lint/assignment_in_condition.rb +1 -1
  17. data/lib/rubocop/cop/lint/condition_position.rb +1 -1
  18. data/lib/rubocop/cop/lint/debugger.rb +1 -1
  19. data/lib/rubocop/cop/lint/deprecated_class_methods.rb +9 -7
  20. data/lib/rubocop/cop/lint/else_layout.rb +1 -1
  21. data/lib/rubocop/cop/lint/empty_ensure.rb +1 -1
  22. data/lib/rubocop/cop/lint/empty_interpolation.rb +22 -0
  23. data/lib/rubocop/cop/lint/end_in_method.rb +1 -1
  24. data/lib/rubocop/cop/lint/ensure_return.rb +1 -1
  25. data/lib/rubocop/cop/lint/eval.rb +1 -1
  26. data/lib/rubocop/cop/lint/literal_in_condition.rb +2 -2
  27. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +9 -0
  28. data/lib/rubocop/cop/lint/loop.rb +2 -2
  29. data/lib/rubocop/cop/lint/require_parentheses.rb +0 -4
  30. data/lib/rubocop/cop/lint/rescue_exception.rb +1 -1
  31. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +1 -1
  32. data/lib/rubocop/cop/lint/space_before_first_arg.rb +36 -0
  33. data/lib/rubocop/cop/lint/string_conversion_in_interpolation.rb +14 -2
  34. data/lib/rubocop/cop/lint/useless_access_modifier.rb +57 -0
  35. data/lib/rubocop/cop/lint/useless_setter_call.rb +1 -1
  36. data/lib/rubocop/cop/lint/void.rb +3 -3
  37. data/lib/rubocop/cop/mixin/space_after_punctuation.rb +1 -1
  38. data/lib/rubocop/cop/offense.rb +3 -21
  39. data/lib/rubocop/cop/rails/action_filter.rb +1 -1
  40. data/lib/rubocop/cop/rails/default_scope.rb +1 -1
  41. data/lib/rubocop/cop/rails/has_and_belongs_to_many.rb +1 -1
  42. data/lib/rubocop/cop/rails/read_write_attribute.rb +43 -0
  43. data/lib/rubocop/cop/rails/scope_args.rb +1 -1
  44. data/lib/rubocop/cop/rails/validation.rb +1 -1
  45. data/lib/rubocop/cop/severity.rb +76 -0
  46. data/lib/rubocop/cop/style/access_modifier_indentation.rb +1 -1
  47. data/lib/rubocop/cop/style/accessor_method_name.rb +2 -2
  48. data/lib/rubocop/cop/style/alias.rb +1 -1
  49. data/lib/rubocop/cop/style/align_hash.rb +1 -1
  50. data/lib/rubocop/cop/style/and_or.rb +1 -1
  51. data/lib/rubocop/cop/style/{favor_join.rb → array_join.rb} +2 -2
  52. data/lib/rubocop/cop/style/begin_block.rb +1 -1
  53. data/lib/rubocop/cop/style/block_nesting.rb +12 -8
  54. data/lib/rubocop/cop/style/braces_around_hash_parameters.rb +1 -1
  55. data/lib/rubocop/cop/style/case_equality.rb +1 -1
  56. data/lib/rubocop/cop/style/case_indentation.rb +5 -5
  57. data/lib/rubocop/cop/style/class_methods.rb +19 -3
  58. data/lib/rubocop/cop/style/class_vars.rb +1 -1
  59. data/lib/rubocop/cop/style/collection_methods.rb +17 -7
  60. data/lib/rubocop/cop/style/colon_method_call.rb +1 -1
  61. data/lib/rubocop/cop/style/{def_parentheses.rb → def_with_parentheses.rb} +0 -0
  62. data/lib/rubocop/cop/style/{hash_methods.rb → deprecated_hash_methods.rb} +5 -4
  63. data/lib/rubocop/cop/style/double_negation.rb +1 -1
  64. data/lib/rubocop/cop/style/empty_lines_around_access_modifier.rb +1 -1
  65. data/lib/rubocop/cop/style/end_block.rb +1 -1
  66. data/lib/rubocop/cop/style/even_odd.rb +2 -2
  67. data/lib/rubocop/cop/style/file_name.rb +1 -1
  68. data/lib/rubocop/cop/style/for.rb +2 -2
  69. data/lib/rubocop/cop/style/format_string.rb +1 -1
  70. data/lib/rubocop/cop/style/guard_clause.rb +69 -0
  71. data/lib/rubocop/cop/style/hash_syntax.rb +6 -10
  72. data/lib/rubocop/cop/style/if_unless_modifier.rb +2 -2
  73. data/lib/rubocop/cop/style/lambda.rb +2 -2
  74. data/lib/rubocop/cop/style/line_end_concatenation.rb +16 -9
  75. data/lib/rubocop/cop/style/multiline_if_then.rb +1 -1
  76. data/lib/rubocop/cop/style/multiline_ternary_operator.rb +2 -2
  77. data/lib/rubocop/cop/style/negated_if.rb +37 -0
  78. data/lib/rubocop/cop/style/negated_while.rb +33 -0
  79. data/lib/rubocop/cop/style/nested_ternary_operator.rb +1 -1
  80. data/lib/rubocop/cop/style/nil_comparison.rb +14 -10
  81. data/lib/rubocop/cop/style/non_nil_check.rb +70 -0
  82. data/lib/rubocop/cop/style/not.rb +25 -1
  83. data/lib/rubocop/cop/style/numeric_literals.rb +1 -1
  84. data/lib/rubocop/cop/style/op_method.rb +4 -4
  85. data/lib/rubocop/cop/style/parentheses_around_condition.rb +1 -1
  86. data/lib/rubocop/cop/style/predicate_name.rb +1 -1
  87. data/lib/rubocop/cop/style/proc.rb +1 -1
  88. data/lib/rubocop/cop/style/raise_args.rb +3 -2
  89. data/lib/rubocop/cop/style/rescue_modifier.rb +1 -1
  90. data/lib/rubocop/cop/style/self_assignment.rb +2 -2
  91. data/lib/rubocop/cop/style/signal_exception.rb +6 -3
  92. data/lib/rubocop/cop/style/single_line_block_params.rb +1 -1
  93. data/lib/rubocop/cop/style/single_line_methods.rb +6 -5
  94. data/lib/rubocop/cop/style/single_space_before_first_arg.rb +41 -0
  95. data/lib/rubocop/cop/style/space_around_operators.rb +1 -2
  96. data/lib/rubocop/cop/style/special_global_vars.rb +8 -8
  97. data/lib/rubocop/cop/style/trailing_comma.rb +1 -1
  98. data/lib/rubocop/cop/style/trivial_accessors.rb +1 -1
  99. data/lib/rubocop/cop/style/unless_else.rb +1 -1
  100. data/lib/rubocop/cop/style/variable_interpolation.rb +10 -5
  101. data/lib/rubocop/cop/style/when_then.rb +1 -1
  102. data/lib/rubocop/cop/style/while_until_modifier.rb +1 -1
  103. data/lib/rubocop/cop/style/word_array.rb +1 -1
  104. data/lib/rubocop/cop/team.rb +12 -13
  105. data/lib/rubocop/cop/util.rb +4 -0
  106. data/lib/rubocop/cop/variable_inspector/locatable.rb +1 -1
  107. data/lib/rubocop/cop/variable_inspector/variable_table.rb +1 -1
  108. data/lib/rubocop/file_inspector.rb +46 -10
  109. data/lib/rubocop/formatter/disabled_config_formatter.rb +1 -1
  110. data/lib/rubocop/formatter/disabled_lines_formatter.rb +56 -0
  111. data/lib/rubocop/formatter/emacs_style_formatter.rb +1 -1
  112. data/lib/rubocop/formatter/formatter_set.rb +2 -1
  113. data/lib/rubocop/formatter/fuubar_style_formatter.rb +2 -4
  114. data/lib/rubocop/formatter/json_formatter.rb +3 -7
  115. data/lib/rubocop/formatter/progress_formatter.rb +1 -3
  116. data/lib/rubocop/formatter/simple_text_formatter.rb +7 -3
  117. data/lib/rubocop/options.rb +29 -10
  118. data/lib/rubocop/path_util.rb +2 -1
  119. data/lib/rubocop/processed_source.rb +8 -0
  120. data/lib/rubocop/target_finder.rb +33 -12
  121. data/lib/rubocop/version.rb +1 -1
  122. data/relnotes/v0.20.0.md +69 -0
  123. data/rubocop-todo.yml +2 -2
  124. data/spec/rubocop/cli_spec.rb +269 -94
  125. data/spec/rubocop/config_loader_spec.rb +14 -14
  126. data/spec/rubocop/config_spec.rb +8 -8
  127. data/spec/rubocop/cop/lint/deprecated_class_methods_spec.rb +11 -6
  128. data/spec/rubocop/cop/lint/empty_interpolation_spec.rb +18 -0
  129. data/spec/rubocop/cop/lint/eval_spec.rb +2 -4
  130. data/spec/rubocop/cop/lint/literal_in_interpolation_spec.rb +10 -0
  131. data/spec/rubocop/cop/lint/rescue_exception_spec.rb +0 -8
  132. data/spec/rubocop/cop/lint/shadowing_outer_local_variable_spec.rb +4 -4
  133. data/spec/rubocop/cop/lint/space_before_first_arg_spec.rb +48 -0
  134. data/spec/rubocop/cop/lint/string_conversion_in_interpolation_spec.rb +10 -0
  135. data/spec/rubocop/cop/lint/useless_access_modifier_spec.rb +154 -0
  136. data/spec/rubocop/cop/offense_spec.rb +1 -1
  137. data/spec/rubocop/cop/rails/read_write_attribute_spec.rb +19 -0
  138. data/spec/rubocop/cop/severity_spec.rb +113 -0
  139. data/spec/rubocop/cop/style/access_modifier_indentation_spec.rb +10 -10
  140. data/spec/rubocop/cop/style/alias_spec.rb +2 -2
  141. data/spec/rubocop/cop/style/and_or_spec.rb +2 -2
  142. data/spec/rubocop/cop/style/{favor_join_spec.rb → array_join_spec.rb} +1 -3
  143. data/spec/rubocop/cop/style/block_nesting_spec.rb +4 -4
  144. data/spec/rubocop/cop/style/case_equality_spec.rb +1 -0
  145. data/spec/rubocop/cop/style/case_indentation_spec.rb +12 -9
  146. data/spec/rubocop/cop/style/class_methods_spec.rb +23 -0
  147. data/spec/rubocop/cop/style/collection_methods_spec.rb +2 -2
  148. data/spec/rubocop/cop/style/{hash_methods_spec.rb → deprecated_hash_methods_spec.rb} +3 -3
  149. data/spec/rubocop/cop/style/empty_lines_around_access_modifier_spec.rb +2 -2
  150. data/spec/rubocop/cop/style/even_odd_spec.rb +8 -8
  151. data/spec/rubocop/cop/style/file_name_spec.rb +55 -42
  152. data/spec/rubocop/cop/style/for_spec.rb +4 -4
  153. data/spec/rubocop/cop/style/format_string_spec.rb +10 -10
  154. data/spec/rubocop/cop/style/guard_clause_spec.rb +77 -0
  155. data/spec/rubocop/cop/style/hash_syntax_spec.rb +4 -2
  156. data/spec/rubocop/cop/style/if_unless_modifier_spec.rb +4 -4
  157. data/spec/rubocop/cop/style/lambda_spec.rb +2 -2
  158. data/spec/rubocop/cop/style/line_end_concatenation_spec.rb +21 -0
  159. data/spec/rubocop/cop/style/multiline_if_then_spec.rb +1 -1
  160. data/spec/rubocop/cop/style/{favor_unless_over_negated_if_spec.rb → negated_if_spec.rb} +8 -3
  161. data/spec/rubocop/cop/style/{favor_until_over_negated_while_spec.rb → negated_while_spec.rb} +8 -3
  162. data/spec/rubocop/cop/style/nil_comparison_spec.rb +7 -13
  163. data/spec/rubocop/cop/style/non_nil_check_spec.rb +35 -0
  164. data/spec/rubocop/cop/style/not_spec.rb +11 -0
  165. data/spec/rubocop/cop/style/numeric_literals_spec.rb +0 -2
  166. data/spec/rubocop/cop/style/op_method_spec.rb +10 -2
  167. data/spec/rubocop/cop/style/parentheses_around_condition_spec.rb +2 -2
  168. data/spec/rubocop/cop/style/predicate_name_spec.rb +2 -1
  169. data/spec/rubocop/cop/style/raise_args_spec.rb +5 -0
  170. data/spec/rubocop/cop/style/rescue_modifier_spec.rb +2 -2
  171. data/spec/rubocop/cop/style/self_assignment_spec.rb +4 -4
  172. data/spec/rubocop/cop/style/signal_exception_spec.rb +24 -0
  173. data/spec/rubocop/cop/style/single_line_block_params_spec.rb +2 -0
  174. data/spec/rubocop/cop/style/single_space_before_first_arg_spec.rb +63 -0
  175. data/spec/rubocop/cop/style/special_global_vars_spec.rb +6 -5
  176. data/spec/rubocop/cop/style/trivial_accessors_spec.rb +6 -3
  177. data/spec/rubocop/cop/style/unless_else_spec.rb +2 -4
  178. data/spec/rubocop/cop/style/variable_interpolation_spec.rb +15 -6
  179. data/spec/rubocop/cop/style/when_then_spec.rb +3 -4
  180. data/spec/rubocop/cop/team_spec.rb +4 -18
  181. data/spec/rubocop/file_inspector_spec.rb +4 -0
  182. data/spec/rubocop/formatter/disabled_config_formatter_spec.rb +1 -1
  183. data/spec/rubocop/formatter/disabled_lines_formatter_spec.rb +69 -0
  184. data/spec/rubocop/options_spec.rb +5 -0
  185. data/spec/rubocop/target_finder_spec.rb +42 -11
  186. data/spec/support/shared_context.rb +1 -1
  187. data/spec/support/statement_modifier_helper.rb +1 -1
  188. metadata +75 -50
  189. data/lib/rubocop/cop/rails/read_attribute.rb +0 -28
  190. data/lib/rubocop/cop/style/favor_unless_over_negated_if.rb +0 -24
  191. data/lib/rubocop/cop/style/favor_until_over_negated_while.rb +0 -20
  192. data/spec/rubocop/cop/rails/read_attribute_spec.rb +0 -13
@@ -6,7 +6,7 @@ module Rubocop
6
6
  # The purpose of the this cop is advise the use of
7
7
  # alias_method over the alias keyword whenever possible.
8
8
  class Alias < Cop
9
- MSG = 'Use alias_method instead of alias.'
9
+ MSG = 'Use `alias_method` instead of `alias`.'
10
10
 
11
11
  def on_block(node)
12
12
  method, _args, body = *node
@@ -196,7 +196,7 @@ module Rubocop
196
196
  end
197
197
 
198
198
  def explicit_hash?(node)
199
- !node.loc.begin.nil?
199
+ node.loc.begin
200
200
  end
201
201
 
202
202
  def multiline?(node)
@@ -5,7 +5,7 @@ module Rubocop
5
5
  module Style
6
6
  # This cop checks for uses of *and* and *or*.
7
7
  class AndOr < Cop
8
- MSG = 'Use %s instead of %s.'
8
+ MSG = 'Use `%s` instead of `%s`.'
9
9
 
10
10
  OPS = { 'and' => '&&', 'or' => '||' }
11
11
 
@@ -8,8 +8,8 @@ module Rubocop
8
8
  # Not all cases can reliably checked, due to Ruby's dynamic
9
9
  # types, so we consider only cases when the first argument is an
10
10
  # array literal or the second is a string literal.
11
- class FavorJoin < Cop
12
- MSG = 'Favor Array#join over Array#*.'
11
+ class ArrayJoin < Cop
12
+ MSG = 'Favor `Array#join` over `Array#*`.'
13
13
 
14
14
  def on_send(node)
15
15
  receiver_node, method_name, *arg_nodes = *node
@@ -5,7 +5,7 @@ module Rubocop
5
5
  module Style
6
6
  # This cop checks for BEGIN blocks.
7
7
  class BeginBlock < Cop
8
- MSG = 'Avoid the use of BEGIN blocks.'
8
+ MSG = 'Avoid the use of `BEGIN` blocks.'
9
9
 
10
10
  def on_preexe(node)
11
11
  add_offense(node, :keyword)
@@ -4,15 +4,17 @@ module Rubocop
4
4
  module Cop
5
5
  module Style
6
6
  # This cop checks for excessive nesting of conditional and looping
7
- # constructs. Despite the cop's name, blocks are not considered as a
7
+ # constructs. Despite the cop's name, blocks are not considered as an
8
8
  # extra level of nesting.
9
9
  #
10
10
  # The maximum level of nesting allowed is configurable.
11
11
  class BlockNesting < Cop
12
12
  include ConfigurableMax
13
13
 
14
- NESTING_BLOCKS = [:case, :if, :while, :while_post, :until, :until_post,
15
- :for, :resbody]
14
+ NESTING_BLOCKS = [
15
+ :case, :if, :while, :while_post,
16
+ :until, :until_post, :for, :resbody
17
+ ]
16
18
 
17
19
  def investigate(processed_source)
18
20
  return unless processed_source.ast
@@ -25,14 +27,16 @@ module Rubocop
25
27
  def check_nesting_level(node, max, current_level)
26
28
  if NESTING_BLOCKS.include?(node.type)
27
29
  unless node.loc.respond_to?(:keyword) &&
28
- node.loc.keyword.is?('elsif')
30
+ node.loc.keyword.is?('elsif')
29
31
  current_level += 1
30
32
  end
31
- if current_level == max + 1
32
- add_offense(node, :expression, message(max)) do
33
- self.max = current_level
33
+ if current_level > max
34
+ self.max = current_level
35
+ unless part_of_ignored_node?(node)
36
+ add_offense(node, :expression, message(max)) do
37
+ ignore_node(node)
38
+ end
34
39
  end
35
- return
36
40
  end
37
41
  end
38
42
  node.children.each do |child|
@@ -75,7 +75,7 @@ module Rubocop
75
75
  end
76
76
 
77
77
  def braces?(arg)
78
- !arg.loc.begin.nil?
78
+ arg.loc.begin
79
79
  end
80
80
 
81
81
  def all_hashes?(args)
@@ -5,7 +5,7 @@ module Rubocop
5
5
  module Style
6
6
  # This cop checks for uses of the case equality operator(===).
7
7
  class CaseEquality < Cop
8
- MSG = 'Avoid the use of the case equality operator(===).'
8
+ MSG = 'Avoid the use of the case equality operator `===`.'
9
9
 
10
10
  def on_send(node)
11
11
  _receiver, method_name, *_args = *node
@@ -31,11 +31,11 @@ module Rubocop
31
31
  if pos.column == expected_column
32
32
  correct_style_detected
33
33
  else
34
- msg = 'Indent when ' + if indent
35
- "one step more than #{base}."
36
- else
37
- "as deep as #{base}."
38
- end
34
+ msg = 'Indent `when` ' + if indent
35
+ "one step more than `#{base}`."
36
+ else
37
+ "as deep as `#{base}`."
38
+ end
39
39
  add_offense(when_node, pos, msg) do
40
40
  if pos.column == base_column(case_node, alternative_style)
41
41
  opposite_style_detected
@@ -6,13 +6,29 @@ module Rubocop
6
6
  # This cop checks for uses of the class/module name instead of
7
7
  # self, when defining class/module methods.
8
8
  class ClassMethods < Cop
9
- MSG = 'Prefer self over class/module for class/module methods.'
9
+ MSG = 'Use `self.%s` instead of `%s.%s`.'
10
10
 
11
11
  # TODO: Check if we're in a class/module
12
12
  def on_defs(node)
13
- definee, _name, _args, _body = *node
13
+ definee, method_name, _args, _body = *node
14
14
 
15
- add_offense(definee, :name) if definee.type == :const
15
+ if definee.type == :const
16
+ _, class_name = *definee
17
+ add_offense(definee, :name,
18
+ message(class_name, method_name))
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ def message(class_name, method_name)
25
+ format(MSG, method_name, class_name, method_name)
26
+ end
27
+
28
+ def autocorrect(node)
29
+ @corrections << lambda do |corrector|
30
+ corrector.replace(node.loc.name, 'self')
31
+ end
16
32
  end
17
33
  end
18
34
  end
@@ -15,7 +15,7 @@ module Rubocop
15
15
 
16
16
  def message(node)
17
17
  class_var, = *node
18
- MSG.format(class_var)
18
+ format(MSG, class_var)
19
19
  end
20
20
  end
21
21
  end
@@ -10,13 +10,7 @@ module Rubocop
10
10
  # enhanced by check for by blocks & procs as arguments of the
11
11
  # methods.
12
12
  class CollectionMethods < Cop
13
- MSG = 'Prefer %s over %s.'
14
-
15
- def preferred_methods
16
- if cop_config['PreferredMethods']
17
- cop_config['PreferredMethods'].symbolize_keys
18
- end
19
- end
13
+ MSG = 'Prefer `%s` over `%s`.'
20
14
 
21
15
  def on_block(node)
22
16
  method, _args, _body = *node
@@ -57,6 +51,22 @@ module Rubocop
57
51
  def preferred_method(method)
58
52
  preferred_methods[method.to_sym]
59
53
  end
54
+
55
+ def preferred_methods
56
+ @preferred_methods ||=
57
+ begin
58
+ # Make sure default configuration 'foo' => 'bar' is removed from
59
+ # the total configuration if there is a 'bar' => 'foo' override.
60
+ default = default_cop_config['PreferredMethods']
61
+ merged = cop_config['PreferredMethods']
62
+ overrides = merged.values - default.values
63
+ merged.reject { |key, _| overrides.include?(key) }.symbolize_keys
64
+ end
65
+ end
66
+
67
+ def default_cop_config
68
+ ConfigLoader.default_configuration[cop_name]
69
+ end
60
70
  end
61
71
  end
62
72
  end
@@ -6,7 +6,7 @@ module Rubocop
6
6
  # This cop checks for methods invoked via the :: operator instead
7
7
  # of the . operator (like FileUtils::rmdir instead of FileUtils.rmdir).
8
8
  class ColonMethodCall < Cop
9
- MSG = 'Do not use :: for method calls.'
9
+ MSG = 'Do not use `::` for method calls.'
10
10
 
11
11
  def on_send(node)
12
12
  receiver, _method_name, *_args = *node
@@ -5,8 +5,8 @@ module Rubocop
5
5
  module Style
6
6
  # This cop checks for uses of the deprecated methods Hash#has_key?
7
7
  # and Hash#has_value?
8
- class HashMethods < Cop
9
- MSG = '%s is deprecated in favor of %s.'
8
+ class DeprecatedHashMethods < Cop
9
+ MSG = '`Hash#%s` is deprecated in favor of `Hash#%s`.'
10
10
 
11
11
  DEPRECATED_METHODS = [:has_key?, :has_value?]
12
12
 
@@ -15,8 +15,9 @@ module Rubocop
15
15
 
16
16
  if args.size == 1 && DEPRECATED_METHODS.include?(method_name)
17
17
  add_offense(node, :selector,
18
- MSG.format(method_name,
19
- proper_method_name(method_name)))
18
+ format(MSG,
19
+ method_name,
20
+ proper_method_name(method_name)))
20
21
  end
21
22
  end
22
23
 
@@ -15,7 +15,7 @@ module Rubocop
15
15
  # # good
16
16
  # !something.nil?
17
17
  class DoubleNegation < Cop
18
- MSG = 'Avoid the use of double negation (!!).'
18
+ MSG = 'Avoid the use of double negation (`!!`).'
19
19
 
20
20
  def on_send(node)
21
21
  return unless not_node?(node)
@@ -5,7 +5,7 @@ module Rubocop
5
5
  module Style
6
6
  # Access modifiers should be surrounded by blank lines.
7
7
  class EmptyLinesAroundAccessModifier < Cop
8
- MSG = 'Keep a blank line before and after %s.'
8
+ MSG = 'Keep a blank line before and after `%s`.'
9
9
 
10
10
  PRIVATE_NODE = s(:send, nil, :private)
11
11
  PROTECTED_NODE = s(:send, nil, :protected)
@@ -5,7 +5,7 @@ module Rubocop
5
5
  module Style
6
6
  # This cop checks for END blocks.
7
7
  class EndBlock < Cop
8
- MSG = 'Avoid the use of END blocks. Use `Kernel#at_exit` instead.'
8
+ MSG = 'Avoid the use of `END` blocks. Use `Kernel#at_exit` instead.'
9
9
 
10
10
  def on_postexe(node)
11
11
  add_offense(node, :keyword)
@@ -14,8 +14,8 @@ module Rubocop
14
14
  # # good
15
15
  # if x.even?
16
16
  class EvenOdd < Cop
17
- MSG_EVEN = 'Use Fixnum.even?'
18
- MSG_ODD = 'Use Fixnum.odd?'
17
+ MSG_EVEN = 'Replace with `Fixnum#even?`.'
18
+ MSG_ODD = 'Replace with `Fixnum#odd?`.'
19
19
 
20
20
  ZERO = s(:int, 0)
21
21
  ONE = s(:int, 1)
@@ -16,7 +16,7 @@ module Rubocop
16
16
 
17
17
  basename = File.basename(file_path).sub(/\.[^\.]+$/, '')
18
18
 
19
- unless basename =~ SNAKE_CASE
19
+ unless basename.split('.').all? { |fragment| fragment =~ SNAKE_CASE }
20
20
  add_offense(nil,
21
21
  source_range(processed_source.buffer,
22
22
  processed_source[0..0],
@@ -12,7 +12,7 @@ module Rubocop
12
12
 
13
13
  def on_for(node)
14
14
  if style == :each
15
- add_offense(node, :keyword, 'Prefer *each* over *for*.') do
15
+ add_offense(node, :keyword, 'Prefer `each` over `for`.') do
16
16
  opposite_style_detected
17
17
  end
18
18
  else
@@ -34,7 +34,7 @@ module Rubocop
34
34
  range = Parser::Source::Range.new(processed_source.buffer,
35
35
  end_pos - 'each'.length,
36
36
  end_pos)
37
- add_offense(range, range, 'Prefer *for* over *each*.') do
37
+ add_offense(range, range, 'Prefer `for` over `each`.') do
38
38
  opposite_style_detected
39
39
  end
40
40
  else
@@ -58,7 +58,7 @@ module Rubocop
58
58
 
59
59
  method_name = 'String#%' if method_name == :%
60
60
 
61
- "Favor #{preferred} over #{method_name}."
61
+ "Favor `#{preferred}` over `#{method_name}`."
62
62
  end
63
63
  end
64
64
  end
@@ -0,0 +1,69 @@
1
+ # encoding: utf-8
2
+
3
+ module Rubocop
4
+ module Cop
5
+ module Style
6
+ # This cop if/unless expression that can be replace with a guard clause.
7
+ #
8
+ # @example
9
+ #
10
+ # # bad
11
+ # def test
12
+ # if something
13
+ # work
14
+ # work
15
+ # work
16
+ # end
17
+ # end
18
+ #
19
+ # # good
20
+ # def test
21
+ # return unless something
22
+ # work
23
+ # work
24
+ # work
25
+ # end
26
+ #
27
+ # It should be extended to handle methods whose body is if/else
28
+ # or a case expression with a default branch.
29
+ class GuardClause < Cop
30
+ include CheckMethods
31
+ include IfNode
32
+
33
+ MSG = 'Use a guard clause instead of wrapping ' \
34
+ 'the code inside a conditional expression.'
35
+
36
+ private
37
+
38
+ def check(_node, _method_name, _args, body)
39
+ return unless body
40
+
41
+ if body.type == :if
42
+ check_if_node(body)
43
+ elsif body.type == :begin
44
+ expressions = *body
45
+ last_expr = expressions.last
46
+
47
+ check_if_node(last_expr) if last_expr && last_expr.type == :if
48
+ end
49
+ end
50
+
51
+ def check_if_node(node)
52
+ _cond, _body, else_body = *node
53
+
54
+ return if else_body
55
+ # discard modifier ifs and ternary_ops
56
+ return if modifier_if?(node) || ternary_op?(node)
57
+ # discard short ifs
58
+ return unless if_length(node) > 3
59
+
60
+ add_offense(node, :keyword)
61
+ end
62
+
63
+ def if_length(node)
64
+ node.loc.end.line - node.loc.keyword.line + 1
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -36,23 +36,19 @@ module Rubocop
36
36
  def autocorrect(node)
37
37
  key = node.children.first.loc.expression
38
38
  op = node.loc.operator
39
- if style == :ruby19 && !space_before_operator?(op, key) &&
40
- config.for_cop('SpaceAroundOperators')['Enabled']
41
- # Don't do the correction if there is no space before '=>'. The
42
- # combined corrections of this cop and SpaceAroundOperators could
43
- # produce code with illegal syntax.
44
- return
45
- end
46
39
 
47
40
  @corrections << lambda do |corrector|
48
41
  if style == :ruby19
49
- corrector.insert_after(key, ' ')
50
- corrector.replace(key, key.source.sub(/^:(.*)/, '\1:'))
42
+ range = Parser::Source::Range.new(key.source_buffer,
43
+ key.begin_pos, op.end_pos)
44
+ range = range_with_surrounding_space(range, :right)
45
+ corrector.replace(range,
46
+ range.source.sub(/^:(.*\S)\s*=>\s*$/, '\1: '))
51
47
  else
52
48
  corrector.insert_after(key, ' => ')
53
49
  corrector.insert_before(key, ':')
50
+ corrector.remove(range_with_surrounding_space(op))
54
51
  end
55
- corrector.remove(range_with_surrounding_space(op))
56
52
  end
57
53
  end
58
54
 
@@ -10,8 +10,8 @@ module Rubocop
10
10
  include StatementModifier
11
11
 
12
12
  def error_message(keyword)
13
- "Favor modifier #{keyword} usage when you have a single-line body." \
14
- ' Another good alternative is the usage of control flow &&/||.'
13
+ "Favor modifier `#{keyword}` usage when having a single-line body." \
14
+ ' Another good alternative is the usage of control flow `&&`/`||`.'
15
15
  end
16
16
 
17
17
  def investigate(processed_source)
@@ -7,8 +7,8 @@ module Rubocop
7
7
  # anonymous functions and uses of the 1.9 lambda syntax for multi-line
8
8
  # anonymous functions.
9
9
  class Lambda < Cop
10
- SINGLE_MSG = 'Use the new lambda literal syntax ->(params) {...}.'
11
- MULTI_MSG = 'Use the lambda method for multi-line lambdas.'
10
+ SINGLE_MSG = 'Use the new lambda literal syntax `->(params) {...}`.'
11
+ MULTI_MSG = 'Use the `lambda` method for multi-line lambdas.'
12
12
 
13
13
  TARGET = s(:send, nil, :lambda)
14
14