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,25 @@
3
3
  module Rubocop
4
4
  module Cop
5
5
  class SymbolArray < Cop
6
- ERROR_MESSAGE = 'Use %i or %I for array of symbols.'
6
+ MSG = 'Use %i or %I for array of symbols.'
7
7
 
8
- def inspect(file, source, tokens, sexp)
8
+ def inspect(source, tokens, ast, comments)
9
9
  # %i and %I were introduced in Ruby 2.0
10
10
  unless RUBY_VERSION < '2.0.0'
11
- each(:array, sexp) do |s|
12
- array_elems = s[1]
11
+ on_node(:array, ast) do |s|
12
+ next unless s.loc.begin && s.loc.begin.source == '['
13
+
14
+ array_elems = s.children
13
15
 
14
16
  # no need to check empty arrays
15
17
  next unless array_elems && array_elems.size > 1
16
18
 
17
- symbol_array = array_elems.all? { |e| e[0] == :symbol_literal }
19
+ symbol_array = array_elems.all? { |e| e.type == :sym }
18
20
 
19
21
  if symbol_array
20
22
  add_offence(:convention,
21
- all_positions(s).first.lineno,
22
- ERROR_MESSAGE)
23
+ s.loc.line,
24
+ MSG)
23
25
  end
24
26
  end
25
27
  end
@@ -0,0 +1,23 @@
1
+ # encoding: utf-8
2
+
3
+ module Rubocop
4
+ module Cop
5
+ class SymbolName < Cop
6
+ MSG = 'Use snake_case for symbols.'
7
+ SNAKE_CASE = /^[\da-z_]+[!?=]?$/
8
+ CAMEL_CASE = /^[A-Z][A-Za-z\d]*$/
9
+
10
+ def allow_camel_case?
11
+ self.class.config['AllowCamelCase']
12
+ end
13
+
14
+ def on_sym(node)
15
+ sym_name = node.to_a[0]
16
+ return unless sym_name =~ /^[a-zA-Z]/
17
+ return if sym_name =~ SNAKE_CASE
18
+ return if allow_camel_case? && sym_name =~ CAMEL_CASE
19
+ add_offence(:convention, node.loc.line, MSG)
20
+ end
21
+ end
22
+ end
23
+ end
@@ -5,26 +5,33 @@ require 'open3'
5
5
  module Rubocop
6
6
  module Cop
7
7
  class Syntax < Cop
8
- def inspect(file, source, tokens, sexp)
8
+ def inspect_file(file)
9
+ # Starting JRuby processes would be extremely slow
10
+ # We need to check if rbx returns nice warning messages
11
+ return unless RUBY_ENGINE == 'ruby'
12
+
9
13
  stderr = nil
10
14
 
11
15
  # it's extremely important to run the syntax check in a
12
16
  # clean environment - otherwise it will be extremely slow
13
17
  if defined? Bundler
14
18
  Bundler.with_clean_env do
15
- _, stderr, _ =
16
- Open3.capture3('ruby -wc', stdin_data: source.join("\n"))
19
+ _, stderr, _ = Open3.capture3("ruby -wc #{file}")
17
20
  end
18
21
  else
19
- _, stderr, _ =
20
- Open3.capture3('ruby -wc', stdin_data: source.join("\n"))
22
+ _, stderr, _ = Open3.capture3("ruby -wc #{file}")
21
23
  end
22
24
 
23
25
  stderr.each_line do |line|
24
26
  # discard lines that are not containing relevant info
25
27
  if line =~ /.+:(\d+): (.+)/
26
- line_no, severity, message = process_line(line)
27
- add_offence(severity, line_no, message)
28
+ # Assignment to unused variables beginning with underscore
29
+ # is reported by Ruby 1.9, but not 2.0. Make 1.9 behave
30
+ # like 2.0.
31
+ unless line =~ /assigned but unused variable - _\w+/
32
+ line_no, severity, message = process_line(line)
33
+ add_offence(severity, line_no, message)
34
+ end
28
35
  end
29
36
  end
30
37
  end
@@ -3,11 +3,11 @@
3
3
  module Rubocop
4
4
  module Cop
5
5
  class Tab < Cop
6
- ERROR_MESSAGE = 'Tab detected.'
6
+ MSG = 'Tab 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 =~ /^ *\t/
10
+ add_offence(:convention, index + 1, MSG) if line =~ /^ *\t/
11
11
  end
12
12
  end
13
13
  end
@@ -2,39 +2,41 @@
2
2
 
3
3
  module Rubocop
4
4
  module Cop
5
- module TernaryOperator
6
- def inspect(file, source, tokens, sexp)
7
- each(:ifop, sexp) do |ifop|
8
- if offends?(ifop)
9
- add_offence(:convention, all_positions(ifop).first.lineno,
10
- error_message)
11
- end
12
- end
13
- end
14
- end
15
-
16
5
  class MultilineTernaryOperator < Cop
17
- include TernaryOperator
18
-
19
- def error_message
6
+ MSG =
20
7
  'Avoid multi-line ?: (the ternary operator); use if/unless instead.'
21
- end
22
8
 
23
- def offends?(ifop)
24
- all_positions(ifop).map(&:lineno).uniq.size > 1
9
+ def on_if(node)
10
+ loc = node.loc
11
+
12
+ # discard non-ternary ops
13
+ return unless loc.respond_to?(:question)
14
+
15
+ add_offence(:convention, loc.line, MSG) if loc.line != loc.colon.line
16
+
17
+ super
25
18
  end
26
19
  end
27
20
 
28
21
  class NestedTernaryOperator < Cop
29
- include TernaryOperator
22
+ MSG = 'Ternary operators must not be nested. Prefer if/else ' +
23
+ 'constructs instead.'
30
24
 
31
- def error_message
32
- 'Ternary operators must not be nested. Prefer if/else constructs ' +
33
- 'instead.'
34
- end
25
+ def on_if(node)
26
+ loc = node.loc
27
+
28
+ # discard non-ternary ops
29
+ return unless loc.respond_to?(:question)
30
+
31
+ node.children.each do |child|
32
+ on_node(:if, child) do |c|
33
+ if c.loc.respond_to?(:question)
34
+ add_offence(:convention, c.loc.line, MSG)
35
+ end
36
+ end
37
+ end
35
38
 
36
- def offends?(ifop)
37
- ifop.flatten[1..-1].include?(:ifop)
39
+ super
38
40
  end
39
41
  end
40
42
  end
@@ -3,13 +3,11 @@
3
3
  module Rubocop
4
4
  module Cop
5
5
  class TrailingWhitespace < Cop
6
- ERROR_MESSAGE = 'Trailing whitespace detected.'
6
+ MSG = 'Trailing whitespace 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
- if line =~ /.*[ \t]+$/
11
- add_offence(:convention, index + 1, ERROR_MESSAGE)
12
- end
10
+ add_offence(:convention, index + 1, MSG) if line =~ /.*[ \t]+$/
13
11
  end
14
12
  end
15
13
  end
@@ -3,101 +3,24 @@
3
3
  module Rubocop
4
4
  module Cop
5
5
  class TrivialAccessors < Cop
6
- READER_MESSAGE = 'Use attr_reader to define trivial reader methods.'
7
- WRITER_MESSAGE = 'Use attr_writer to define trivial writer methods.'
8
-
9
- def inspect(file, source, token, sexp)
10
- each(:def, sexp) do |def_block|
11
- find_trivial_accessors def_block
12
- end
13
- end
14
-
15
- private
16
-
17
- # Parse the sexp given, corresponding to a def method.
18
- # Looking for a trivial reader/writer pattern
19
- def find_trivial_accessors(sexp)
20
- lineno = sexp[1][2].lineno
21
- accessor_var = sexp[1][1]
22
- if trivial_reader?(sexp, accessor_var)
23
- add_offence(:convention, lineno, READER_MESSAGE)
24
- elsif trivial_writer?(sexp, accessor_var)
25
- add_offence(:convention, lineno, WRITER_MESSAGE)
26
- end
27
- end
28
-
29
- # body statements that exclude a trivial accessor
30
- NON_TRIVIAL_BODYSTMT = [:void_stmt, :unary, :binary,
31
- :@float, :@int, :hash, :begin,
32
- :yield0, :zsuper, :array]
33
-
34
- # looking for a trivial reader method
35
- def trivial_reader?(sexp, accessor_var)
36
- if reader_shape?(sexp)
37
- accessor_body = sexp[3][1][0][1][1]
38
- accessor_body.slice!(0) if accessor_body[0] == '@'
39
- accessor_var == accessor_body
40
- end
41
- end
42
-
43
- # looking for a trivial writer method
44
- def trivial_writer?(sexp, accessor_var)
45
- if accessor_var[-1] == '=' &&
46
- writer_shape?(sexp) &&
47
- has_only_one_assignment?(sexp)
48
- accessor_var.chop!
49
- accessor_body = sexp[3][1][0][1][1][1]
50
- accessor_body.slice!(0) if accessor_body[0] == '@'
51
- unless sexp[3][1][0][0] == :vcall
52
- body_purpose = sexp[3][1][0][2][0]
53
- accessor_var == accessor_body && body_purpose == :var_ref
54
- end
6
+ MSG = 'Use attr_%s to define trivial %s methods.'
7
+
8
+ def on_def(node)
9
+ _, args, body = *node
10
+
11
+ kind = if body.type == :ivar
12
+ 'reader'
13
+ elsif args.children.size == 1 && body.type == :ivasgn &&
14
+ body.children[1].type == :lvar
15
+ 'writer'
16
+ end
17
+ if kind
18
+ add_offence(:convention, node.loc.keyword.line,
19
+ sprintf(MSG, kind, kind))
55
20
  end
56
- end
57
-
58
- # return true if the sexp is a reader accessor, without params
59
- # or with empty braces
60
- def reader_shape?(sexp)
61
- accessor_shape?(sexp) &&
62
- (sexp[2][0] == :params || empty_params?(sexp[2]))
63
- end
64
-
65
- # return true if the sexp is a writer accessor, with a param
66
- # and with or without braces
67
- def writer_shape?(sexp)
68
- accessor_shape?(sexp) && with_braces?(sexp[2])
69
- end
70
-
71
- # return true if the sexp has the common shape of an accessor
72
- def accessor_shape?(sexp)
73
- [:@ident, :@const].include?(sexp[1][0]) &&
74
- sexp[3][0] == :bodystmt &&
75
- !NON_TRIVIAL_BODYSTMT.include?(sexp[3][1][0][0])
76
- end
77
-
78
- # detect "def foo() ..." or
79
- # "[:paren, [:params, nil, nil, nil, nil, nil, nil, nil]]"
80
- def empty_params?(sexp)
81
- sexp[0] == :paren &&
82
- sexp[1][0] == :params &&
83
- sexp[1][1..-1].reject { |x| !x }.empty?
84
- end
85
21
 
86
- # detect "def name= name" or "def name=(name)
87
- def with_braces?(sexp)
88
- (sexp[0] == :paren && sexp[1][0] == :params) ||
89
- sexp[0] == :params
22
+ super
90
23
  end
91
-
92
- # return true if the sexp has only one assignment in the body
93
- # false otherwise (maybe one or more function calls).
94
- # why [3..-1]? because:
95
- # [:bodystmt, [[:assign, [:var_field, [:var_ref ...] and no :vcall
96
- # thus [:bodystmt, :assign, :var_ref, nil, nil, nil ...]
97
- def has_only_one_assignment?(sexp)
98
- sexp[3][1][1] == nil
99
- end
100
-
101
- end # TrivialAccessors
102
- end # Cop
103
- end # Rubocop
24
+ end
25
+ end
26
+ end
@@ -3,16 +3,20 @@
3
3
  module Rubocop
4
4
  module Cop
5
5
  class UnlessElse < Cop
6
- ERROR_MESSAGE = 'Never use unless with else. Rewrite these with the ' +
6
+ MSG = 'Never use unless with else. Rewrite these with the ' +
7
7
  'positive case first.'
8
8
 
9
- def inspect(file, source, tokens, sexp)
10
- each(:unless, sexp) do |unless_sexp|
11
- if unless_sexp.compact.any? { |s| s[0] == :else }
12
- add_offence(:convention, all_positions(unless_sexp).first.lineno,
13
- ERROR_MESSAGE)
14
- end
9
+ def on_if(node)
10
+ loc = node.loc
11
+
12
+ # discard ternary ops and modifier if/unless nodes
13
+ return unless loc.respond_to?(:keyword) && loc.respond_to?(:else)
14
+
15
+ if loc.keyword.source == 'unless' && loc.else
16
+ add_offence(:convention, loc.line, MSG)
15
17
  end
18
+
19
+ super
16
20
  end
17
21
  end
18
22
  end
@@ -0,0 +1,26 @@
1
+ # encoding: utf-8
2
+
3
+ module Rubocop
4
+ module Cop
5
+ module Util
6
+ module_function
7
+
8
+ def strip_quotes(str)
9
+ if str[0] == '"' || str[0] == "'"
10
+ str[0] = ''
11
+ str[-1] = ''
12
+ else
13
+ # we're dealing with %q or %Q
14
+ str[0, 3] = ''
15
+ str[-1] = ''
16
+ end
17
+
18
+ str
19
+ end
20
+
21
+ def block_length(block_node)
22
+ block_node.loc.end.line - block_node.loc.begin.line
23
+ end
24
+ end
25
+ end
26
+ end
@@ -3,18 +3,26 @@
3
3
  module Rubocop
4
4
  module Cop
5
5
  class VariableInterpolation < Cop
6
- def inspect(file, source, tokens, sexp)
7
- each(:string_dvar, sexp) do |s|
8
- interpolation = s[1][0] == :@backref ? s[1] : s[1][1]
9
- var = interpolation[1]
10
- lineno = interpolation[2].lineno
6
+ MSG = 'Replace interpolated var %s with expression #{%s}.'
11
7
 
12
- add_offence(
13
- :convention,
14
- lineno,
15
- "Replace interpolated var #{var} with expression \#{#{var}}."
16
- )
8
+ def on_dstr(node)
9
+ var_nodes(node.children).each do |v|
10
+ var = (v.type == :nth_ref ? '$' : '') + v.to_a[0].to_s
11
+
12
+ if node.loc.expression.source.include?("##{var}")
13
+ add_offence(:convention,
14
+ v.loc.line,
15
+ sprintf(MSG, var, var))
16
+ end
17
17
  end
18
+
19
+ super
20
+ end
21
+
22
+ private
23
+
24
+ def var_nodes(nodes)
25
+ nodes.select { |n| [:ivar, :cvar, :gvar, :nth_ref].include?(n.type) }
18
26
  end
19
27
  end
20
28
  end
@@ -3,25 +3,14 @@
3
3
  module Rubocop
4
4
  module Cop
5
5
  class WhenThen < Cop
6
- ERROR_MESSAGE = 'Never use "when x;". Use "when x then" instead.'
6
+ MSG = 'Never use "when x;". Use "when x then" instead.'
7
7
 
8
- def inspect(file, source, tokens, sexp)
9
- each(:when, sexp) do |s|
10
- # The grammar is:
11
- # when <value> <divider> <body>
12
- # where divider is either semicolon, then, or line break.
13
- last_pos_in_value = all_positions(s[1])[-1]
14
-
15
- next unless last_pos_in_value # Give up if no positions found.
16
-
17
- start_index = tokens.index { |t| t.pos == last_pos_in_value }
18
- tokens[start_index..-1].each do |t|
19
- break if ['then', "\n"].include?(t.text)
20
- if t.type == :on_semicolon
21
- add_offence(:convention, t.pos.lineno, ERROR_MESSAGE)
22
- end
23
- end
8
+ def on_when(node)
9
+ if node.loc.begin && node.loc.begin.source == ';'
10
+ add_offence(:convention, node.loc.line, MSG)
24
11
  end
12
+
13
+ super
25
14
  end
26
15
  end
27
16
  end
@@ -3,35 +3,34 @@
3
3
  module Rubocop
4
4
  module Cop
5
5
  class WordArray < Cop
6
- ERROR_MESSAGE = 'Use %w or %W for array of words.'
6
+ MSG = 'Use %w or %W for array of words.'
7
7
 
8
- def inspect(file, source, tokens, sexp)
9
- each(:array, sexp) do |s|
10
- array_elems = s[1]
8
+ def on_array(node)
9
+ return unless node.loc.begin && node.loc.begin.source == '['
11
10
 
12
- # no need to check empty arrays
13
- next unless array_elems && array_elems.size > 1
11
+ array_elems = node.children
14
12
 
15
- string_array = array_elems.all? { |e| e[0] == :string_literal }
13
+ # no need to check empty arrays
14
+ return unless array_elems && array_elems.size > 1
16
15
 
17
- if string_array && !complex_content?(array_elems)
18
- add_offence(:convention,
19
- all_positions(s).first.lineno,
20
- ERROR_MESSAGE)
21
- end
16
+ string_array = array_elems.all? { |e| e.type == :str }
17
+
18
+ if string_array && !complex_content?(array_elems)
19
+ add_offence(:convention, node.loc.line, MSG)
22
20
  end
21
+
22
+ super
23
23
  end
24
24
 
25
- def complex_content?(arr_sexp)
26
- non_empty_strings = 0
25
+ private
27
26
 
28
- each(:@tstring_content, arr_sexp) do |content|
29
- non_empty_strings += 1
30
- return true unless content[1] =~ /\A[\w-]+\z/
27
+ def complex_content?(arr_sexp)
28
+ arr_sexp.each do |s|
29
+ str_content = Util.strip_quotes(s.loc.expression.source)
30
+ return true unless str_content =~ /\A[\w-]+\z/
31
31
  end
32
32
 
33
- # check for '' strings in the array
34
- non_empty_strings == arr_sexp.size ? false : true
33
+ false
35
34
  end
36
35
  end
37
36
  end