rubocop 0.7.2 → 0.8.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 (184) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +7 -1
  3. data/CHANGELOG.md +19 -0
  4. data/README.md +4 -8
  5. data/bin/rubocop +2 -2
  6. data/config/default.yml +8 -0
  7. data/config/enabled.yml +21 -24
  8. data/lib/rubocop.rb +9 -7
  9. data/lib/rubocop/cli.rb +73 -52
  10. data/lib/rubocop/config.rb +8 -5
  11. data/lib/rubocop/cop/access_control.rb +41 -0
  12. data/lib/rubocop/cop/alias.rb +7 -5
  13. data/lib/rubocop/cop/align_parameters.rb +20 -96
  14. data/lib/rubocop/cop/and_or.rb +26 -0
  15. data/lib/rubocop/cop/ascii_comments.rb +3 -8
  16. data/lib/rubocop/cop/ascii_identifiers.rb +6 -5
  17. data/lib/rubocop/cop/avoid_class_vars.rb +5 -10
  18. data/lib/rubocop/cop/avoid_for.rb +7 -5
  19. data/lib/rubocop/cop/avoid_global_vars.rb +19 -7
  20. data/lib/rubocop/cop/avoid_perl_backrefs.rb +7 -10
  21. data/lib/rubocop/cop/avoid_perlisms.rb +11 -10
  22. data/lib/rubocop/cop/block_comments.rb +4 -6
  23. data/lib/rubocop/cop/blocks.rb +11 -47
  24. data/lib/rubocop/cop/case_indentation.rb +9 -31
  25. data/lib/rubocop/cop/class_and_module_camel_case.rb +20 -11
  26. data/lib/rubocop/cop/class_methods.rb +5 -10
  27. data/lib/rubocop/cop/collection_methods.rb +16 -16
  28. data/lib/rubocop/cop/colon_method_call.rb +8 -32
  29. data/lib/rubocop/cop/constant_name.rb +24 -0
  30. data/lib/rubocop/cop/cop.rb +20 -78
  31. data/lib/rubocop/cop/def_parentheses.rb +43 -35
  32. data/lib/rubocop/cop/empty_line_between_defs.rb +11 -15
  33. data/lib/rubocop/cop/empty_lines.rb +20 -9
  34. data/lib/rubocop/cop/empty_literal.rb +47 -0
  35. data/lib/rubocop/cop/encoding.rb +3 -3
  36. data/lib/rubocop/cop/end_of_line.rb +3 -3
  37. data/lib/rubocop/cop/ensure_return.rb +6 -23
  38. data/lib/rubocop/cop/eval.rb +7 -10
  39. data/lib/rubocop/cop/favor_join.rb +9 -24
  40. data/lib/rubocop/cop/favor_modifier.rb +38 -48
  41. data/lib/rubocop/cop/favor_percent_r.rb +7 -7
  42. data/lib/rubocop/cop/favor_sprintf.rb +8 -24
  43. data/lib/rubocop/cop/favor_unless_over_negated_if.rb +19 -17
  44. data/lib/rubocop/cop/handle_exceptions.rb +7 -11
  45. data/lib/rubocop/cop/hash_syntax.rb +29 -14
  46. data/lib/rubocop/cop/if_then_else.rb +32 -29
  47. data/lib/rubocop/cop/leading_comment_space.rb +5 -8
  48. data/lib/rubocop/cop/line_continuation.rb +4 -7
  49. data/lib/rubocop/cop/line_length.rb +3 -3
  50. data/lib/rubocop/cop/loop.rb +33 -0
  51. data/lib/rubocop/cop/method_and_variable_snake_case.rb +42 -19
  52. data/lib/rubocop/cop/method_length.rb +34 -37
  53. data/lib/rubocop/cop/new_lambda_literal.rb +8 -6
  54. data/lib/rubocop/cop/not.rb +10 -4
  55. data/lib/rubocop/cop/numeric_literals.rb +9 -7
  56. data/lib/rubocop/cop/offence.rb +1 -1
  57. data/lib/rubocop/cop/op_method.rb +12 -22
  58. data/lib/rubocop/cop/parameter_lists.rb +12 -6
  59. data/lib/rubocop/cop/parentheses_around_condition.rb +11 -11
  60. data/lib/rubocop/cop/percent_r.rb +7 -7
  61. data/lib/rubocop/cop/reduce_arguments.rb +13 -51
  62. data/lib/rubocop/cop/rescue_exception.rb +13 -29
  63. data/lib/rubocop/cop/rescue_modifier.rb +5 -8
  64. data/lib/rubocop/cop/semicolon.rb +15 -74
  65. data/lib/rubocop/cop/single_line_methods.rb +28 -44
  66. data/lib/rubocop/cop/space_after_comma_etc.rb +29 -9
  67. data/lib/rubocop/cop/space_after_control_keyword.rb +16 -15
  68. data/lib/rubocop/cop/string_literals.rb +9 -35
  69. data/lib/rubocop/cop/surrounding_space.rb +213 -112
  70. data/lib/rubocop/cop/symbol_array.rb +9 -7
  71. data/lib/rubocop/cop/symbol_name.rb +23 -0
  72. data/lib/rubocop/cop/syntax.rb +14 -7
  73. data/lib/rubocop/cop/tab.rb +3 -3
  74. data/lib/rubocop/cop/ternary_operator.rb +26 -24
  75. data/lib/rubocop/cop/trailing_whitespace.rb +3 -5
  76. data/lib/rubocop/cop/trivial_accessors.rb +18 -95
  77. data/lib/rubocop/cop/unless_else.rb +11 -7
  78. data/lib/rubocop/cop/util.rb +26 -0
  79. data/lib/rubocop/cop/variable_interpolation.rb +18 -10
  80. data/lib/rubocop/cop/when_then.rb +6 -17
  81. data/lib/rubocop/cop/word_array.rb +18 -19
  82. data/lib/rubocop/version.rb +1 -1
  83. data/rubocop.gemspec +1 -0
  84. data/spec/project_spec.rb +1 -1
  85. data/spec/rubocop/cli_spec.rb +16 -9
  86. data/spec/rubocop/config_spec.rb +13 -3
  87. data/spec/rubocop/cops/access_control_spec.rb +129 -0
  88. data/spec/rubocop/cops/alias_spec.rb +2 -6
  89. data/spec/rubocop/cops/align_parameters_spec.rb +58 -71
  90. data/spec/rubocop/cops/and_or_spec.rb +37 -0
  91. data/spec/rubocop/cops/ascii_comments_spec.rb +3 -4
  92. data/spec/rubocop/cops/ascii_identifiers_spec.rb +3 -4
  93. data/spec/rubocop/cops/avoid_class_vars_spec.rb +7 -2
  94. data/spec/rubocop/cops/avoid_for_spec.rb +1 -4
  95. data/spec/rubocop/cops/{avoid_global_vars.rb → avoid_global_vars_spec.rb} +4 -4
  96. data/spec/rubocop/cops/avoid_perl_backrefs_spec.rb +1 -1
  97. data/spec/rubocop/cops/avoid_perlisms_spec.rb +5 -5
  98. data/spec/rubocop/cops/block_comments_spec.rb +0 -4
  99. data/spec/rubocop/cops/blocks_spec.rb +33 -0
  100. data/spec/rubocop/cops/case_indentation_spec.rb +5 -5
  101. data/spec/rubocop/cops/class_and_module_camel_case_spec.rb +15 -5
  102. data/spec/rubocop/cops/class_methods_spec.rb +4 -4
  103. data/spec/rubocop/cops/collection_methods_spec.rb +9 -4
  104. data/spec/rubocop/cops/colon_method_call_spec.rb +11 -5
  105. data/spec/rubocop/cops/constant_name_spec.rb +42 -0
  106. data/spec/rubocop/cops/def_with_parentheses_spec.rb +13 -8
  107. data/spec/rubocop/cops/def_without_parentheses_spec.rb +11 -5
  108. data/spec/rubocop/cops/empty_line_between_defs_spec.rb +38 -38
  109. data/spec/rubocop/cops/empty_lines_spec.rb +15 -3
  110. data/spec/rubocop/cops/empty_literal_spec.rb +90 -0
  111. data/spec/rubocop/cops/encoding_spec.rb +9 -9
  112. data/spec/rubocop/cops/end_of_line_spec.rb +2 -2
  113. data/spec/rubocop/cops/ensure_return_spec.rb +1 -3
  114. data/spec/rubocop/cops/eval_spec.rb +8 -5
  115. data/spec/rubocop/cops/favor_join_spec.rb +1 -5
  116. data/spec/rubocop/cops/favor_modifier_spec.rb +16 -14
  117. data/spec/rubocop/cops/{favor_percent_r.rb → favor_percent_r_spec.rb} +6 -6
  118. data/spec/rubocop/cops/favor_sprintf_spec.rb +3 -9
  119. data/spec/rubocop/cops/favor_unless_over_negated_if_spec.rb +4 -4
  120. data/spec/rubocop/cops/favor_until_over_negated_while_spec.rb +3 -3
  121. data/spec/rubocop/cops/handle_exceptions_spec.rb +1 -3
  122. data/spec/rubocop/cops/hash_syntax_spec.rb +11 -6
  123. data/spec/rubocop/cops/if_with_semicolon_spec.rb +7 -1
  124. data/spec/rubocop/cops/leading_comment_space_spec.rb +0 -7
  125. data/spec/rubocop/cops/line_continuation_spec.rb +2 -2
  126. data/spec/rubocop/cops/line_length_spec.rb +2 -2
  127. data/spec/rubocop/cops/loop_spec.rb +31 -0
  128. data/spec/rubocop/cops/method_and_variable_snake_case_spec.rb +38 -12
  129. data/spec/rubocop/cops/method_length_spec.rb +85 -85
  130. data/spec/rubocop/cops/multiline_if_then_spec.rb +15 -15
  131. data/spec/rubocop/cops/new_lambda_literal_spec.rb +3 -3
  132. data/spec/rubocop/cops/not_spec.rb +1 -4
  133. data/spec/rubocop/cops/numeric_literals_spec.rb +13 -13
  134. data/spec/rubocop/cops/one_line_conditional_spec.rb +1 -1
  135. data/spec/rubocop/cops/op_method_spec.rb +2 -9
  136. data/spec/rubocop/cops/parameter_lists_spec.rb +7 -7
  137. data/spec/rubocop/cops/parentheses_around_condition_spec.rb +41 -44
  138. data/spec/rubocop/cops/percent_r_spec.rb +6 -6
  139. data/spec/rubocop/cops/reduce_arguments_spec.rb +4 -4
  140. data/spec/rubocop/cops/rescue_exception_spec.rb +48 -8
  141. data/spec/rubocop/cops/rescue_modifier_spec.rb +2 -5
  142. data/spec/rubocop/cops/semicolon_spec.rb +2 -30
  143. data/spec/rubocop/cops/single_line_methods_spec.rb +13 -13
  144. data/spec/rubocop/cops/space_after_colon_spec.rb +3 -3
  145. data/spec/rubocop/cops/space_after_comma_spec.rb +14 -2
  146. data/spec/rubocop/cops/space_after_control_keyword_spec.rb +42 -3
  147. data/spec/rubocop/cops/space_after_semicolon_spec.rb +2 -2
  148. data/spec/rubocop/cops/space_around_braces_spec.rb +18 -3
  149. data/spec/rubocop/cops/space_around_equals_in_default_parameter_spec.rb +4 -4
  150. data/spec/rubocop/cops/space_around_operators_spec.rb +82 -27
  151. data/spec/rubocop/cops/space_inside_brackets_spec.rb +13 -7
  152. data/spec/rubocop/cops/space_inside_hash_literal_braces_spec.rb +14 -9
  153. data/spec/rubocop/cops/space_inside_parens_spec.rb +7 -3
  154. data/spec/rubocop/cops/string_literals_spec.rb +17 -5
  155. data/spec/rubocop/cops/symbol_array_spec.rb +18 -2
  156. data/spec/rubocop/cops/symbol_name_spec.rb +119 -0
  157. data/spec/rubocop/cops/syntax_spec.rb +25 -18
  158. data/spec/rubocop/cops/tab_spec.rb +2 -2
  159. data/spec/rubocop/cops/ternary_operator_spec.rb +13 -17
  160. data/spec/rubocop/cops/trailing_whitespace_spec.rb +3 -3
  161. data/spec/rubocop/cops/trivial_accessors_spec.rb +17 -20
  162. data/spec/rubocop/cops/unless_else_spec.rb +8 -8
  163. data/spec/rubocop/cops/variable_interpolation_spec.rb +0 -5
  164. data/spec/rubocop/cops/when_then_spec.rb +14 -21
  165. data/spec/rubocop/cops/word_array_spec.rb +12 -4
  166. data/spec/spec_helper.rb +12 -4
  167. metadata +40 -31
  168. data/.document +0 -5
  169. data/lib/rubocop/cop/ampersands_pipes_vs_and_or.rb +0 -25
  170. data/lib/rubocop/cop/array_literal.rb +0 -61
  171. data/lib/rubocop/cop/brace_after_percent.rb +0 -32
  172. data/lib/rubocop/cop/grammar.rb +0 -138
  173. data/lib/rubocop/cop/hash_literal.rb +0 -61
  174. data/lib/rubocop/cop/percent_literals.rb +0 -25
  175. data/lib/rubocop/cop/symbol_snake_case.rb +0 -47
  176. data/spec/rubocop/cops/ampersands_pipes_vs_and_or_spec.rb +0 -57
  177. data/spec/rubocop/cops/array_literal_spec.rb +0 -46
  178. data/spec/rubocop/cops/brace_after_percent_spec.rb +0 -33
  179. data/spec/rubocop/cops/grammar_spec.rb +0 -81
  180. data/spec/rubocop/cops/hash_literal_spec.rb +0 -46
  181. data/spec/rubocop/cops/multiline_blocks_spec.rb +0 -24
  182. data/spec/rubocop/cops/percent_literals_spec.rb +0 -47
  183. data/spec/rubocop/cops/single_line_blocks_spec.rb +0 -22
  184. data/spec/rubocop/cops/symbol_snake_case_spec.rb +0 -93
@@ -3,23 +3,19 @@
3
3
  module Rubocop
4
4
  module Cop
5
5
  class EmptyLineBetweenDefs < Cop
6
- ERROR_MESSAGE = 'Use empty lines between defs.'
6
+ MSG = 'Use empty lines between defs.'
7
7
 
8
- def inspect(file, source, tokens, sexp)
9
- each_parent_of(:def, sexp) do |parent|
10
- defs = parent.select { |child| child[0] == :def }
11
- identifier_of_first_def = defs[0][1]
12
- current_row_ix = identifier_of_first_def[-1].lineno - 1
13
- # The first def doesn't need to have an empty line above it,
14
- # so we iterate starting at index 1.
15
- defs[1..-1].each do |child|
16
- next_row_ix = child[1][-1].lineno - 1
17
- if source[current_row_ix..next_row_ix].grep(/^[ \t]*$/).empty?
18
- add_offence(:convention, next_row_ix + 1, ERROR_MESSAGE)
19
- end
20
- current_row_ix = next_row_ix
21
- end
8
+ def on_def(s)
9
+ def_start = s.loc.keyword.line
10
+ def_end = s.loc.end.line
11
+
12
+ if @prev_def_end && (def_start - @prev_def_end) < 2
13
+ add_offence(:convention, def_start, MSG)
22
14
  end
15
+
16
+ @prev_def_end = def_end
17
+
18
+ super
23
19
  end
24
20
  end
25
21
  end
@@ -3,19 +3,30 @@
3
3
  module Rubocop
4
4
  module Cop
5
5
  class EmptyLines < Cop
6
- ERROR_MESSAGE = 'Extra blank line detected.'
6
+ MSG = 'Extra blank line detected.'
7
+ LINE_OFFSET = 2
7
8
 
8
- def inspect(file, source, tokens, sexp)
9
- previous_token = Token.new(0, :init, '')
9
+ def inspect(source, tokens, ast, comments)
10
+ return if tokens.empty?
10
11
 
11
- tokens.each do |t|
12
- if t.type == :on_ignored_nl && previous_token.type == :on_ignored_nl
13
- add_offence(:convention,
14
- t.pos.lineno,
15
- ERROR_MESSAGE)
12
+ prev_line = 1
13
+
14
+ tokens.each do |token|
15
+ cur_line = token.pos.line
16
+ line_diff = cur_line - prev_line
17
+
18
+ if line_diff > LINE_OFFSET
19
+ # we need to be wary of comments since they
20
+ # don't show up in the tokens
21
+ ((prev_line + 1)...cur_line).each do |line|
22
+ # we check if the prev and current lines are empty
23
+ if source[line - 2].empty? && source[line - 1].empty?
24
+ add_offence(:convention, line, MSG)
25
+ end
26
+ end
16
27
  end
17
28
 
18
- previous_token = t
29
+ prev_line = cur_line
19
30
  end
20
31
  end
21
32
  end
@@ -0,0 +1,47 @@
1
+ # encoding: utf-8
2
+
3
+ module Rubocop
4
+ module Cop
5
+ class EmptyLiteral < Cop
6
+ ARR_MSG = 'Use array literal [] instead of Array.new.'
7
+ HASH_MSG = 'Use hash literal {} instead of Hash.new.'
8
+ STR_MSG = "Use string literal '' instead of String.new."
9
+
10
+ # Empty array node
11
+ #
12
+ # (send
13
+ # (const nil :Array) :new)
14
+ ARRAY_NODE = s(:send, s(:const, nil, :Array), :new)
15
+
16
+ # Empty hash node
17
+ #
18
+ # (send
19
+ # (const nil :Hash) :new)
20
+ HASH_NODE = s(:send, s(:const, nil, :Hash), :new)
21
+
22
+ # Empty string node
23
+ #
24
+ # (send
25
+ # (const nil :String) :new)
26
+ STR_NODE = s(:send, s(:const, nil, :String), :new)
27
+
28
+ def inspect(source, tokens, ast, comments)
29
+ on_node(:send, ast, :block) do |node|
30
+ if node == ARRAY_NODE
31
+ add_offence(:convention,
32
+ node.loc.line,
33
+ ARR_MSG)
34
+ elsif node == HASH_NODE
35
+ add_offence(:convention,
36
+ node.loc.line,
37
+ HASH_MSG)
38
+ elsif node == STR_NODE
39
+ add_offence(:convention,
40
+ node.loc.line,
41
+ STR_MSG)
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -3,14 +3,14 @@
3
3
  module Rubocop
4
4
  module Cop
5
5
  class Encoding < Cop
6
- ERROR_MESSAGE = 'Missing utf-8 encoding comment.'
6
+ MSG = 'Missing utf-8 encoding comment.'
7
7
 
8
- def inspect(file, source, tokens, sexp)
8
+ def inspect(source, tokens, ast, comments)
9
9
  unless RUBY_VERSION >= '2.0.0'
10
10
  expected_line = 0
11
11
  expected_line += 1 if source[expected_line] =~ /^#!/
12
12
  unless source[expected_line] =~ /#.*coding: (UTF|utf)-8/
13
- add_offence(:convention, 1, ERROR_MESSAGE)
13
+ add_offence(:convention, 1, MSG)
14
14
  end
15
15
  end
16
16
  end
@@ -3,11 +3,11 @@
3
3
  module Rubocop
4
4
  module Cop
5
5
  class EndOfLine < Cop
6
- ERROR_MESSAGE = 'Carriage return character detected.'
6
+ MSG = 'Carriage return character detected.'
7
7
 
8
- def inspect(file, source, tokens, sexp)
8
+ def inspect(source, tokens, ast, comments)
9
9
  source.each_with_index do |line, index|
10
- add_offence(:convention, index + 1, ERROR_MESSAGE) if line =~ /\r$/
10
+ add_offence(:convention, index + 1, MSG) if line =~ /\r$/
11
11
  end
12
12
  end
13
13
  end
@@ -3,33 +3,16 @@
3
3
  module Rubocop
4
4
  module Cop
5
5
  class EnsureReturn < Cop
6
- ERROR_MESSAGE = 'Never return from an ensure block.'
6
+ MSG = 'Never return from an ensure block.'
7
7
 
8
- def inspect(file, source, tokens, sexp)
9
- in_ensure = false
10
- ensure_col = nil
8
+ def on_ensure(node)
9
+ _body, ensure_body = *node
11
10
 
12
- tokens.each_index do |ix|
13
- t = tokens[ix]
14
- if ensure_start?(t)
15
- in_ensure = true
16
- ensure_col = t.pos.column
17
- elsif ensure_end?(t, ensure_col)
18
- in_ensure = false
19
- elsif in_ensure && t.type == :on_kw && t.text == 'return'
20
- add_offence(:warning, t.pos.lineno, ERROR_MESSAGE)
21
- end
11
+ on_node(:return, ensure_body) do |e|
12
+ add_offence(:warning, e.loc.line, MSG)
22
13
  end
23
- end
24
-
25
- private
26
-
27
- def ensure_start?(t)
28
- t.type == :on_kw && t.text == 'ensure'
29
- end
30
14
 
31
- def ensure_end?(t, column)
32
- t.type == :on_kw && t.text == 'end' && t.pos.column == column
15
+ super
33
16
  end
34
17
  end
35
18
  end
@@ -3,19 +3,16 @@
3
3
  module Rubocop
4
4
  module Cop
5
5
  class Eval < Cop
6
- ERROR_MESSAGE = 'The use of eval is a serious security risk.'
6
+ MSG = 'The use of eval is a serious security risk.'
7
7
 
8
- def inspect(file, source, tokens, sexp)
9
- each(:command, sexp) { |s| process_ident(s[1]) }
10
- each(:fcall, sexp) { |s| process_ident(s[1]) }
11
- end
8
+ def on_send(node)
9
+ receiver, method_name, = *node
12
10
 
13
- def process_ident(sexp)
14
- if sexp[0] == :@ident && sexp[1] == 'eval'
15
- add_offence(:security,
16
- sexp[2].lineno,
17
- ERROR_MESSAGE)
11
+ if receiver.nil? && method_name == :eval
12
+ add_offence(:security, node.loc.line, MSG)
18
13
  end
14
+
15
+ super
19
16
  end
20
17
  end
21
18
  end
@@ -3,34 +3,19 @@
3
3
  module Rubocop
4
4
  module Cop
5
5
  class FavorJoin < Cop
6
- ERROR_MESSAGE = 'Favor Array#join over Array#*.'
6
+ MSG = 'Favor Array#join over Array#*.'
7
7
 
8
- def inspect(file, source, tokens, sexp)
9
- each(:binary, sexp) do |s|
10
- op1 = s[1]
11
- operator = s[2]
12
- op2 = s[3]
8
+ def on_send(node)
9
+ receiver_node, method_name, *arg_nodes = *node
13
10
 
14
- # we care only about the * operator
15
- next unless matching?(operator, op1, op2)
16
-
17
- pos = all_positions(s[1]).first
18
- lineno = pos.lineno if pos
19
-
20
- add_offence(
21
- :convention,
22
- lineno,
23
- ERROR_MESSAGE
24
- ) if lineno
11
+ if receiver_node && receiver_node.type == :array &&
12
+ method_name == :* && arg_nodes[0].type == :str
13
+ add_offence(:convention,
14
+ node.loc.expression.line,
15
+ MSG)
25
16
  end
26
- end
27
-
28
- private
29
-
30
- def matching?(operator, op1, op2)
31
- return false unless operator == :*
32
17
 
33
- op1[0] == :array and op2[0] == :string_literal
18
+ super
34
19
  end
35
20
  end
36
21
  end
@@ -3,53 +3,36 @@
3
3
  module Rubocop
4
4
  module Cop
5
5
  module FavorModifier
6
- def check(kind, tokens, sexp)
7
- token_positions = tokens.map(&:pos)
8
- token_texts = tokens.map(&:text)
9
- each(kind, sexp) do |s|
10
- # If it contains an else, it can't be written as a modifier.
11
- next if s[3] && s[3][0] == :else
6
+ # TODO extremely ugly solution that needs lots of polish
7
+ def check(sexp)
8
+ # discard if/then/else
9
+ return false if sexp.loc.respond_to?(:else) && sexp.loc.else
12
10
 
13
- sexp_positions = all_positions(s)
14
- ix = token_positions.index(sexp_positions.first)
15
- if_ix = token_texts[0..ix].rindex(kind.to_s) # index of if/unless/...
16
- ix = token_positions.index(sexp_positions.last)
17
- end_ix = ix + token_texts[ix..-1].index('end')
11
+ if %w(if while).include?(sexp.loc.keyword.source)
12
+ cond, body = *sexp
13
+ else
14
+ cond, _else, body = *sexp
15
+ end
18
16
 
19
- # If there's a comment anywhere between
20
- # if/unless/while/until and end, we don't report. It's
21
- # possible that the comment will be less clear if put above
22
- # a one liner rather than inside.
23
- next if tokens[if_ix...end_ix].map(&:type).include?(:on_comment)
17
+ if length(sexp) > 3
18
+ false
19
+ else
20
+ cond_length = sexp.loc.keyword.size + cond.loc.expression.size + 1
21
+ body_length = body_length(body)
24
22
 
25
- if token_positions[end_ix].lineno - token_positions[if_ix].lineno > 2
26
- next # not a single-line body
27
- end
28
- # The start ix is the index of the leftmost token on the
29
- # line of the if/unless, i.e. the index of if/unless itself,
30
- # or of the indentation space.
31
- start_ix = if_ix.downto(0).find do |block_ix|
32
- block_ix == 0 || tokens[block_ix - 1].text =~ /\n/
33
- end
34
- # The stop index is the index of the token just before
35
- # 'end', not counting whitespace tokens.
36
- stop_ix = (end_ix - 1).downto(0).find do |block_ix|
37
- tokens[block_ix].text !~ /\s/
38
- end
39
- if length(tokens, start_ix, stop_ix) <= LineLength.max
40
- add_offence(:convention, token_positions[if_ix].lineno,
41
- error_message)
42
- end
23
+ (cond_length + body_length) <= LineLength.max
43
24
  end
44
25
  end
45
26
 
46
- def length(tokens, start_ix, stop_ix)
47
- (start_ix..stop_ix).reduce(0) do |acc, ix|
48
- acc + if ix > start_ix && tokens[ix - 1].text =~ /\n/
49
- 0
50
- else
51
- tokens[ix].text.length
52
- end
27
+ def length(sexp)
28
+ sexp.loc.expression.source.split("\n").size
29
+ end
30
+
31
+ def body_length(body)
32
+ if body
33
+ body.loc.expression.column + body.loc.expression.size
34
+ else
35
+ 0
53
36
  end
54
37
  end
55
38
  end
@@ -59,23 +42,30 @@ module Rubocop
59
42
 
60
43
  def error_message
61
44
  'Favor modifier if/unless usage when you have a single-line body. ' +
62
- 'Another good alternative is the usage of control flow and/or.'
45
+ 'Another good alternative is the usage of control flow &&/||.'
63
46
  end
64
47
 
65
- def inspect(file, source, tokens, sexp)
66
- [:if, :unless].each { |kind| check(kind, tokens, sexp) }
48
+ def on_if(node)
49
+ # discard ternary ops and modifier if/unless nodes
50
+ return unless node.loc.respond_to?(:keyword) &&
51
+ node.loc.respond_to?(:else)
52
+
53
+ add_offence(:convention, node.loc.line, error_message) if check(node)
54
+
55
+ super
67
56
  end
68
57
  end
69
58
 
70
59
  class WhileUntilModifier < Cop
71
60
  include FavorModifier
72
61
 
73
- def error_message
62
+ MSG =
74
63
  'Favor modifier while/until usage when you have a single-line body.'
75
- end
76
64
 
77
- def inspect(file, source, tokens, sexp)
78
- [:while, :until].each { |kind| check(kind, tokens, sexp) }
65
+ def inspect(source, tokens, ast, comments)
66
+ on_node([:while, :until], ast) do |node|
67
+ add_offence(:convention, node.loc.line, MSG) if check(node)
68
+ end
79
69
  end
80
70
  end
81
71
  end
@@ -3,16 +3,16 @@
3
3
  module Rubocop
4
4
  module Cop
5
5
  class FavorPercentR < Cop
6
- ERROR_MESSAGE = 'Use %r for regular expressions matching more ' +
6
+ MSG = 'Use %r for regular expressions matching more ' +
7
7
  "than one '/' character."
8
8
 
9
- def inspect(file, source, tokens, sexp)
10
- tokens.each_cons(2) do |t1, t2|
11
- if t1.type == :on_regexp_beg && t1.text == '/' &&
12
- t2.text.scan(/\//).size > 1
13
- add_offence(:convention, t1.pos.lineno, ERROR_MESSAGE)
14
- end
9
+ def on_regexp(node)
10
+ if node.loc.begin.source == '/' &&
11
+ node.loc.expression.source[1...-1].scan(/\//).size > 1
12
+ add_offence(:convention, node.loc.line, MSG)
15
13
  end
14
+
15
+ super
16
16
  end
17
17
  end
18
18
  end
@@ -3,34 +3,18 @@
3
3
  module Rubocop
4
4
  module Cop
5
5
  class FavorSprintf < Cop
6
- ERROR_MESSAGE = 'Favor sprintf over String#%.'
6
+ MSG = 'Favor sprintf over String#%.'
7
7
 
8
- def inspect(file, source, tokens, sexp)
9
- each(:binary, sexp) do |s|
10
- op1 = s[1]
11
- operator = s[2]
12
- op2 = s[3]
8
+ def on_send(node)
9
+ receiver_node, method_name, *arg_nodes = *node
13
10
 
14
- # we care only about the % operator
15
- next unless matching?(operator, op1, op2)
16
-
17
- pos = all_positions(s[1]).first
18
- lineno = pos.lineno if pos
19
-
20
- add_offence(
21
- :convention,
22
- lineno,
23
- ERROR_MESSAGE
24
- ) if lineno
11
+ if method_name == :% &&
12
+ ([:str, :dstr].include?(receiver_node.type) ||
13
+ arg_nodes[0].type == :array)
14
+ add_offence(:convention, node.loc.expression.line, MSG)
25
15
  end
26
- end
27
-
28
- private
29
-
30
- def matching?(operator, op1, op2)
31
- return false unless operator == :%
32
16
 
33
- op1[0] == :string_literal or op2[0] == :array
17
+ super
34
18
  end
35
19
  end
36
20
  end