rubocop 0.9.1 → 0.10.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 (149) hide show
  1. data/.travis.yml +3 -1
  2. data/CHANGELOG.md +38 -0
  3. data/README.md +34 -0
  4. data/Rakefile +3 -0
  5. data/config/default.yml +14 -1
  6. data/config/enabled.yml +30 -7
  7. data/lib/rubocop.rb +15 -0
  8. data/lib/rubocop/cli.rb +48 -154
  9. data/lib/rubocop/config.rb +19 -22
  10. data/lib/rubocop/config_store.rb +2 -4
  11. data/lib/rubocop/cop/commissioner.rb +90 -0
  12. data/lib/rubocop/cop/cop.rb +38 -31
  13. data/lib/rubocop/cop/corrector.rb +84 -0
  14. data/lib/rubocop/cop/lint/assignment_in_condition.rb +0 -3
  15. data/lib/rubocop/cop/lint/block_alignment.rb +151 -0
  16. data/lib/rubocop/cop/lint/empty_ensure.rb +18 -0
  17. data/lib/rubocop/cop/lint/end_alignment.rb +0 -124
  18. data/lib/rubocop/cop/lint/end_in_method.rb +0 -2
  19. data/lib/rubocop/cop/lint/ensure_return.rb +3 -3
  20. data/lib/rubocop/cop/lint/eval.rb +0 -2
  21. data/lib/rubocop/cop/lint/handle_exceptions.rb +0 -2
  22. data/lib/rubocop/cop/lint/literal_in_condition.rb +0 -10
  23. data/lib/rubocop/cop/lint/loop.rb +0 -2
  24. data/lib/rubocop/cop/lint/rescue_exception.rb +0 -2
  25. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +2 -2
  26. data/lib/rubocop/cop/lint/unreachable_code.rb +0 -2
  27. data/lib/rubocop/cop/lint/unused_local_variable.rb +2 -2
  28. data/lib/rubocop/cop/lint/void.rb +0 -2
  29. data/lib/rubocop/cop/offence.rb +9 -0
  30. data/lib/rubocop/cop/rails/validation.rb +2 -1
  31. data/lib/rubocop/cop/style/access_control.rb +4 -3
  32. data/lib/rubocop/cop/style/alias.rb +2 -4
  33. data/lib/rubocop/cop/style/align_parameters.rb +0 -2
  34. data/lib/rubocop/cop/style/and_or.rb +4 -6
  35. data/lib/rubocop/cop/style/ascii_comments.rb +2 -2
  36. data/lib/rubocop/cop/style/ascii_identifiers.rb +2 -2
  37. data/lib/rubocop/cop/style/attr.rb +0 -2
  38. data/lib/rubocop/cop/style/avoid_class_vars.rb +0 -1
  39. data/lib/rubocop/cop/style/avoid_for.rb +0 -2
  40. data/lib/rubocop/cop/style/avoid_global_vars.rb +3 -7
  41. data/lib/rubocop/cop/style/avoid_perl_backrefs.rb +0 -2
  42. data/lib/rubocop/cop/style/avoid_perlisms.rb +2 -4
  43. data/lib/rubocop/cop/style/begin_block.rb +0 -2
  44. data/lib/rubocop/cop/style/block_comments.rb +2 -2
  45. data/lib/rubocop/cop/style/block_nesting.rb +3 -3
  46. data/lib/rubocop/cop/style/blocks.rb +0 -2
  47. data/lib/rubocop/cop/style/case_equality.rb +0 -2
  48. data/lib/rubocop/cop/style/case_indentation.rb +0 -2
  49. data/lib/rubocop/cop/style/character_literal.rb +10 -6
  50. data/lib/rubocop/cop/style/class_and_module_camel_case.rb +0 -4
  51. data/lib/rubocop/cop/style/class_methods.rb +1 -1
  52. data/lib/rubocop/cop/style/collection_methods.rb +3 -5
  53. data/lib/rubocop/cop/style/colon_method_call.rb +3 -3
  54. data/lib/rubocop/cop/style/comment_annotation.rb +44 -0
  55. data/lib/rubocop/cop/style/constant_name.rb +0 -2
  56. data/lib/rubocop/cop/style/def_parentheses.rb +0 -8
  57. data/lib/rubocop/cop/style/documentation.rb +6 -2
  58. data/lib/rubocop/cop/style/dot_position.rb +0 -2
  59. data/lib/rubocop/cop/style/empty_line_between_defs.rb +0 -2
  60. data/lib/rubocop/cop/style/empty_lines.rb +10 -8
  61. data/lib/rubocop/cop/style/empty_literal.rb +3 -1
  62. data/lib/rubocop/cop/style/encoding.rb +7 -6
  63. data/lib/rubocop/cop/style/end_block.rb +0 -2
  64. data/lib/rubocop/cop/style/end_of_line.rb +4 -3
  65. data/lib/rubocop/cop/style/favor_join.rb +0 -2
  66. data/lib/rubocop/cop/style/favor_modifier.rb +9 -9
  67. data/lib/rubocop/cop/style/favor_sprintf.rb +0 -2
  68. data/lib/rubocop/cop/style/favor_unless_over_negated_if.rb +0 -2
  69. data/lib/rubocop/cop/style/hash_syntax.rb +0 -2
  70. data/lib/rubocop/cop/style/if_then_else.rb +0 -2
  71. data/lib/rubocop/cop/style/lambda.rb +0 -2
  72. data/lib/rubocop/cop/style/leading_comment_space.rb +2 -2
  73. data/lib/rubocop/cop/style/line_continuation.rb +4 -3
  74. data/lib/rubocop/cop/style/line_length.rb +4 -3
  75. data/lib/rubocop/cop/style/method_and_variable_snake_case.rb +4 -3
  76. data/lib/rubocop/cop/style/method_call_parentheses.rb +0 -2
  77. data/lib/rubocop/cop/style/method_length.rb +0 -4
  78. data/lib/rubocop/cop/style/not.rb +0 -2
  79. data/lib/rubocop/cop/style/op_method.rb +0 -2
  80. data/lib/rubocop/cop/style/parameter_lists.rb +0 -2
  81. data/lib/rubocop/cop/style/parentheses_around_condition.rb +12 -6
  82. data/lib/rubocop/cop/style/proc.rb +0 -2
  83. data/lib/rubocop/cop/style/reduce_arguments.rb +0 -2
  84. data/lib/rubocop/cop/style/redundant_begin.rb +45 -0
  85. data/lib/rubocop/cop/style/redundant_return.rb +59 -0
  86. data/lib/rubocop/cop/style/redundant_self.rb +83 -0
  87. data/lib/rubocop/cop/style/regexp_literal.rb +0 -2
  88. data/lib/rubocop/cop/style/rescue_modifier.rb +13 -21
  89. data/lib/rubocop/cop/style/semicolon.rb +15 -9
  90. data/lib/rubocop/cop/style/single_line_methods.rb +0 -4
  91. data/lib/rubocop/cop/style/space_after_comma_etc.rb +2 -2
  92. data/lib/rubocop/cop/style/space_after_control_keyword.rb +0 -1
  93. data/lib/rubocop/cop/style/string_literals.rb +5 -2
  94. data/lib/rubocop/cop/style/surrounding_space.rb +106 -91
  95. data/lib/rubocop/cop/style/tab.rb +4 -3
  96. data/lib/rubocop/cop/style/ternary_operator.rb +0 -4
  97. data/lib/rubocop/cop/style/trailing_whitespace.rb +4 -3
  98. data/lib/rubocop/cop/style/trivial_accessors.rb +51 -6
  99. data/lib/rubocop/cop/style/unless_else.rb +0 -2
  100. data/lib/rubocop/cop/style/variable_interpolation.rb +0 -2
  101. data/lib/rubocop/cop/style/when_then.rb +3 -3
  102. data/lib/rubocop/cop/style/while_until_do.rb +3 -5
  103. data/lib/rubocop/cop/style/word_array.rb +0 -2
  104. data/lib/rubocop/cop/util.rb +0 -4
  105. data/lib/rubocop/formatter/file_list_formatter.rb +18 -0
  106. data/lib/rubocop/formatter/formatter_set.rb +2 -1
  107. data/lib/rubocop/processed_source.rb +27 -0
  108. data/lib/rubocop/rake_task.rb +50 -0
  109. data/lib/rubocop/source_parser.rb +105 -0
  110. data/lib/rubocop/target_finder.rb +67 -0
  111. data/lib/rubocop/token.rb +22 -0
  112. data/lib/rubocop/version.rb +1 -1
  113. data/rubocop.gemspec +5 -3
  114. data/spec/project_spec.rb +0 -11
  115. data/spec/rubocop/cli_spec.rb +112 -6
  116. data/spec/rubocop/config_spec.rb +13 -17
  117. data/spec/rubocop/config_store_spec.rb +8 -23
  118. data/spec/rubocop/cops/commissioner_spec.rb +72 -0
  119. data/spec/rubocop/cops/corrector_spec.rb +63 -0
  120. data/spec/rubocop/cops/lint/assignment_in_condition_spec.rb +2 -2
  121. data/spec/rubocop/cops/lint/block_alignment_spec.rb +357 -0
  122. data/spec/rubocop/cops/lint/empty_ensure_spec.rb +33 -0
  123. data/spec/rubocop/cops/lint/end_alignment_spec.rb +0 -263
  124. data/spec/rubocop/cops/lint/ensure_return_spec.rb +6 -9
  125. data/spec/rubocop/cops/offence_spec.rb +28 -0
  126. data/spec/rubocop/cops/style/and_or_spec.rb +21 -11
  127. data/spec/rubocop/cops/style/ascii_identifiers_spec.rb +14 -0
  128. data/spec/rubocop/cops/style/avoid_global_vars_spec.rb +10 -14
  129. data/spec/rubocop/cops/style/character_literal_spec.rb +17 -2
  130. data/spec/rubocop/cops/style/colon_method_call_spec.rb +20 -15
  131. data/spec/rubocop/cops/style/comment_annotation_spec.rb +62 -0
  132. data/spec/rubocop/cops/style/encoding_spec.rb +7 -0
  133. data/spec/rubocop/cops/style/parentheses_around_condition_spec.rb +37 -9
  134. data/spec/rubocop/cops/style/redundant_begin_spec.rb +63 -0
  135. data/spec/rubocop/cops/style/redundant_return_spec.rb +64 -0
  136. data/spec/rubocop/cops/style/redundant_self_spec.rb +76 -0
  137. data/spec/rubocop/cops/style/string_literals_spec.rb +18 -13
  138. data/spec/rubocop/cops/style/trivial_accessors_spec.rb +110 -52
  139. data/spec/rubocop/cops/style/when_then_spec.rb +14 -7
  140. data/spec/rubocop/cops/style/while_until_do_spec.rb +12 -0
  141. data/spec/rubocop/cops/variable_inspector_spec.rb +3 -5
  142. data/spec/rubocop/formatter/file_list_formatter_spec.rb +33 -0
  143. data/spec/rubocop/processed_source_spec.rb +67 -0
  144. data/spec/rubocop/source_parser_spec.rb +141 -0
  145. data/spec/rubocop/target_finder_spec.rb +180 -0
  146. data/spec/rubocop/token_spec.rb +27 -0
  147. data/spec/spec_helper.rb +24 -4
  148. metadata +108 -18
  149. checksums.yaml +0 -7
@@ -29,6 +29,8 @@ module Rubocop
29
29
  STR_NODE = s(:send, s(:const, nil, :String), :new)
30
30
 
31
31
  def on_send(node)
32
+ return if part_of_ignored_node?(node)
33
+
32
34
  case node
33
35
  when ARRAY_NODE
34
36
  add_offence(:convention,
@@ -45,7 +47,7 @@ module Rubocop
45
47
  end
46
48
  end
47
49
 
48
- # TODO Check block contents as well
50
+ # TODO: Check block contents as well.
49
51
  alias_method :on_block, :ignore_node
50
52
  end
51
53
  end
@@ -10,14 +10,15 @@ module Rubocop
10
10
  class Encoding < Cop
11
11
  MSG = 'Missing utf-8 encoding comment.'
12
12
 
13
- def inspect(source_buffer, source, tokens, ast, comments)
13
+ def investigate(processed_source)
14
14
  unless RUBY_VERSION >= '2.0.0'
15
- expected_line = 0
16
- expected_line += 1 if source[expected_line] =~ /^#!/
17
- unless source[expected_line] =~ /#.*coding: (UTF|utf)-8/
15
+ line_number = 0
16
+ line_number += 1 if processed_source[line_number] =~ /^#!/
17
+ line = processed_source[line_number]
18
+ unless line =~ /#.*coding\s?: (UTF|utf)-8/
18
19
  add_offence(:convention,
19
- source_range(source_buffer,
20
- source[0...expected_line],
20
+ source_range(processed_source.buffer,
21
+ processed_source[0...line_number],
21
22
  0, 1),
22
23
  MSG)
23
24
  end
@@ -9,8 +9,6 @@ module Rubocop
9
9
 
10
10
  def on_postexe(node)
11
11
  add_offence(:convention, node.loc.keyword, MSG)
12
-
13
- super
14
12
  end
15
13
  end
16
14
  end
@@ -7,11 +7,12 @@ module Rubocop
7
7
  class EndOfLine < Cop
8
8
  MSG = 'Carriage return character detected.'
9
9
 
10
- def inspect(source_buffer, source, tokens, ast, comments)
11
- source.each_with_index do |line, index|
10
+ def investigate(processed_source)
11
+ processed_source.lines.each_with_index do |line, index|
12
12
  if line =~ /\r$/
13
13
  add_offence(:convention,
14
- source_range(source_buffer, source[0...index],
14
+ source_range(processed_source.buffer,
15
+ processed_source[0...index],
15
16
  line.length - 1, 1),
16
17
  MSG)
17
18
  end
@@ -20,8 +20,6 @@ module Rubocop
20
20
  node.loc.selector,
21
21
  MSG)
22
22
  end
23
-
24
- super
25
23
  end
26
24
  end
27
25
  end
@@ -5,7 +5,7 @@ module Rubocop
5
5
  module Style
6
6
  # Common functionality for modifier cops.
7
7
  module FavorModifier
8
- # TODO extremely ugly solution that needs lots of polish
8
+ # TODO: Extremely ugly solution that needs lots of polish.
9
9
  def check(sexp, comments)
10
10
  case sexp.loc.keyword.source
11
11
  when 'if' then cond, body, _else = *sexp
@@ -61,16 +61,16 @@ module Rubocop
61
61
  'Another good alternative is the usage of control flow &&/||.'
62
62
  end
63
63
 
64
- def inspect(source_buffer, source, tokens, ast, comments)
65
- return unless ast
66
- on_node(:if, ast) do |node|
64
+ def investigate(processed_source)
65
+ return unless processed_source.ast
66
+ on_node(:if, processed_source.ast) do |node|
67
67
  # discard ternary ops, if/else and modifier if/unless nodes
68
68
  return if ternary_op?(node)
69
69
  return if modifier_if?(node)
70
70
  return if elsif?(node)
71
71
  return if if_else?(node)
72
72
 
73
- if check(node, comments)
73
+ if check(node, processed_source.comments)
74
74
  add_offence(:convention, node.loc.expression, error_message)
75
75
  end
76
76
  end
@@ -101,13 +101,13 @@ module Rubocop
101
101
  MSG =
102
102
  'Favor modifier while/until usage when you have a single-line body.'
103
103
 
104
- def inspect(source_buffer, source, tokens, ast, comments)
105
- return unless ast
106
- on_node([:while, :until], ast) do |node|
104
+ def investigate(processed_source)
105
+ return unless processed_source.ast
106
+ on_node([:while, :until], processed_source.ast) do |node|
107
107
  # discard modifier while/until
108
108
  next unless node.loc.end
109
109
 
110
- if check(node, comments)
110
+ if check(node, processed_source.comments)
111
111
  add_offence(:convention, node.loc.expression, MSG)
112
112
  end
113
113
  end
@@ -19,8 +19,6 @@ module Rubocop
19
19
  arg_nodes[0].type == :array)
20
20
  add_offence(:convention, node.loc.selector, MSG)
21
21
  end
22
-
23
- super
24
22
  end
25
23
  end
26
24
  end
@@ -28,7 +28,6 @@ module Rubocop
28
28
 
29
29
  def on_if(node)
30
30
  check(node)
31
- super
32
31
  end
33
32
 
34
33
  def error_message
@@ -42,7 +41,6 @@ module Rubocop
42
41
 
43
42
  def on_while(node)
44
43
  check(node)
45
- super
46
44
  end
47
45
 
48
46
  def error_message
@@ -24,8 +24,6 @@ module Rubocop
24
24
  end
25
25
  end
26
26
  end
27
-
28
- super
29
27
  end
30
28
 
31
29
  private
@@ -7,12 +7,10 @@ module Rubocop
7
7
  module IfThenElse
8
8
  def on_if(node)
9
9
  check(node)
10
- super
11
10
  end
12
11
 
13
12
  def on_unless(node)
14
13
  check(node)
15
- super
16
14
  end
17
15
 
18
16
  def check(node)
@@ -29,8 +29,6 @@ module Rubocop
29
29
  add_offence(:convention, block_method.loc.expression, MULTI_MSG)
30
30
  end
31
31
  end
32
-
33
- super
34
32
  end
35
33
 
36
34
  private
@@ -10,8 +10,8 @@ module Rubocop
10
10
  class LeadingCommentSpace < Cop
11
11
  MSG = 'Missing space after #.'
12
12
 
13
- def inspect(source_buffer, source, tokens, ast, comments)
14
- comments.each do |comment|
13
+ def investigate(processed_source)
14
+ processed_source.comments.each do |comment|
15
15
  if comment.text =~ /^#+[^#\s:+-]/
16
16
  unless comment.text.start_with?('#!') && comment.loc.line == 1
17
17
  add_offence(:convention, comment.loc, MSG)
@@ -10,11 +10,12 @@ module Rubocop
10
10
  class LineContinuation < Cop
11
11
  MSG = 'Avoid the use of the line continuation character(\).'
12
12
 
13
- def inspect(source_buffer, source, tokens, ast, comments)
14
- source.each_with_index do |line, index|
13
+ def investigate(processed_source)
14
+ processed_source.lines.each_with_index do |line, index|
15
15
  if line =~ /.*\\\z/
16
16
  add_offence(:convention,
17
- source_range(source_buffer, source[0...index],
17
+ source_range(processed_source.buffer,
18
+ processed_source[0...index],
18
19
  line.length - 1, 1),
19
20
  MSG)
20
21
  end
@@ -8,13 +8,14 @@ module Rubocop
8
8
  class LineLength < Cop
9
9
  MSG = 'Line is too long. [%d/%d]'
10
10
 
11
- def inspect(source_buffer, source, tokens, ast, comments)
12
- source.each_with_index do |line, index|
11
+ def investigate(processed_source)
12
+ processed_source.lines.each_with_index do |line, index|
13
13
  max = LineLength.max
14
14
  if line.length > max
15
15
  message = sprintf(MSG, line.length, max)
16
16
  add_offence(:convention,
17
- source_range(source_buffer, source[0...index], max,
17
+ source_range(processed_source.buffer,
18
+ processed_source[0...index], max,
18
19
  line.length - max),
19
20
  message)
20
21
  end
@@ -16,9 +16,10 @@ module Rubocop
16
16
  + - * / % ** ~ +@ -@ [] []= ` ! != !~
17
17
  ).map(&:to_sym)
18
18
 
19
- def inspect(source_buffer, source, tokens, node, comments)
20
- return unless node
21
- on_node([:def, :defs, :lvasgn, :ivasgn, :send], node) do |n|
19
+ def investigate(processed_source)
20
+ ast = processed_source.ast
21
+ return unless ast
22
+ on_node([:def, :defs, :lvasgn, :ivasgn, :send], ast) do |n|
22
23
  name = case n.type
23
24
  when :def
24
25
  name_of_instance_method(n)
@@ -13,8 +13,6 @@ module Rubocop
13
13
  if args.empty? && node.loc.begin
14
14
  add_offence(:convention, node.loc.begin, MSG)
15
15
  end
16
-
17
- super
18
16
  end
19
17
  end
20
18
  end
@@ -11,14 +11,10 @@ module Rubocop
11
11
 
12
12
  def on_def(node)
13
13
  check(node)
14
-
15
- super
16
14
  end
17
15
 
18
16
  def on_defs(node)
19
17
  check(node)
20
-
21
- super
22
18
  end
23
19
 
24
20
  def max_length
@@ -15,8 +15,6 @@ module Rubocop
15
15
  node.loc.selector.is?('not')
16
16
  add_offence(:convention, node.loc.selector, MSG)
17
17
  end
18
-
19
- super
20
18
  end
21
19
  end
22
20
  end
@@ -20,8 +20,6 @@ module Rubocop
20
20
  add_offence(:convention, args.children[0].loc.expression,
21
21
  sprintf(MSG, name))
22
22
  end
23
-
24
- super
25
23
  end
26
24
  end
27
25
  end
@@ -15,8 +15,6 @@ module Rubocop
15
15
  add_offence(:convention, node.loc.expression,
16
16
  sprintf(MSG, max_params))
17
17
  end
18
-
19
- super
20
18
  end
21
19
 
22
20
  private
@@ -6,25 +6,20 @@ module Rubocop
6
6
  # This cop checks for the presence of superfluous parentheses around the
7
7
  # condition of if/while/until.
8
8
  class ParenthesesAroundCondition < Cop
9
+ ASGN_NODES = [:lvasgn, :ivasgn, :cvasgn, :gvasgn, :casgn]
9
10
  MSG = "Don't use parentheses around the condition of an " +
10
11
  'if/unless/while/until'
11
12
 
12
13
  def on_if(node)
13
14
  process_control_op(node)
14
-
15
- super
16
15
  end
17
16
 
18
17
  def on_while(node)
19
18
  process_control_op(node)
20
-
21
- super
22
19
  end
23
20
 
24
21
  def on_until(node)
25
22
  process_control_op(node)
26
-
27
- super
28
23
  end
29
24
 
30
25
  private
@@ -33,9 +28,20 @@ module Rubocop
33
28
  cond, _body = *node
34
29
 
35
30
  if cond.type == :begin
31
+ # allow safe assignment
32
+ return if safe_assignment?(cond) && safe_assignment_allowed?
33
+
36
34
  add_offence(:convention, cond.loc.expression, MSG)
37
35
  end
38
36
  end
37
+
38
+ def safe_assignment?(node)
39
+ node.children.size == 1 && ASGN_NODES.include?(node.children[0].type)
40
+ end
41
+
42
+ def safe_assignment_allowed?
43
+ ParenthesesAroundCondition.config['AllowSafeAssignment']
44
+ end
39
45
  end
40
46
  end
41
47
  end
@@ -21,8 +21,6 @@ module Rubocop
21
21
  if block_method == TARGET
22
22
  add_offence(:convention, block_method.loc.expression, MSG)
23
23
  end
24
-
25
- super
26
24
  end
27
25
  end
28
26
  end
@@ -25,8 +25,6 @@ module Rubocop
25
25
  unless args_node == ARGS_NODE
26
26
  add_offence(:convention, node.loc.expression, MSG)
27
27
  end
28
-
29
- super
30
28
  end
31
29
  end
32
30
  end
@@ -0,0 +1,45 @@
1
+ # encoding: utf-8
2
+
3
+ module Rubocop
4
+ module Cop
5
+ module Style
6
+ # This cop checks for redundant `begin` blocks.
7
+ #
8
+ # Currently it checks for code like this:
9
+ #
10
+ # @example
11
+ #
12
+ # def test
13
+ # begin
14
+ # ala
15
+ # bala
16
+ # rescue StandardError => e
17
+ # something
18
+ # end
19
+ # end
20
+ class RedundantBegin < Cop
21
+ MSG = 'Redundant `begin` block detected.'
22
+
23
+ def on_def(node)
24
+ _method_name, _args, body = *node
25
+
26
+ check(body)
27
+ end
28
+
29
+ def on_defs(node)
30
+ _scope, _method_name, _args, body = *node
31
+
32
+ check(body)
33
+ end
34
+
35
+ private
36
+
37
+ def check(node)
38
+ return unless node && node.type == :kwbegin
39
+
40
+ add_offence(:convention, node.loc.begin, MSG)
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,59 @@
1
+ # encoding: utf-8
2
+
3
+ module Rubocop
4
+ module Cop
5
+ module Style
6
+ # This cop checks for redundant `return` expressions.
7
+ #
8
+ # Currently it checks for code like this:
9
+ #
10
+ # @example
11
+ #
12
+ # def test
13
+ # return something
14
+ # end
15
+ #
16
+ # def test
17
+ # one
18
+ # two
19
+ # three
20
+ # return something
21
+ # end
22
+ #
23
+ # It should be extended to handle methods whose body is if/else
24
+ # or a case expression with a default branch.
25
+ class RedundantReturn < Cop
26
+ MSG = 'Redundant `return` detected.'
27
+
28
+ def on_def(node)
29
+ _method_name, _args, body = *node
30
+
31
+ check(body)
32
+ end
33
+
34
+ def on_defs(node)
35
+ _scope, _method_name, _args, body = *node
36
+
37
+ check(body)
38
+ end
39
+
40
+ private
41
+
42
+ def check(node)
43
+ return unless node
44
+
45
+ if node.type == :return
46
+ add_offence(:convention, node.loc.keyword, MSG)
47
+ elsif node.type == :begin
48
+ expressions = *node
49
+ last_expr = expressions.last
50
+
51
+ if last_expr && last_expr.type == :return
52
+ add_offence(:convention, last_expr.loc.keyword, MSG)
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end