rubocop 0.4.0 → 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 (190) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +50 -0
  3. data/.rubocop.yml +5 -127
  4. data/.travis.yml +7 -1
  5. data/CHANGELOG.md +157 -0
  6. data/CONTRIBUTING.md +13 -6
  7. data/Gemfile +3 -8
  8. data/README.md +160 -9
  9. data/Rakefile +3 -17
  10. data/bin/rubocop +16 -10
  11. data/config/default.yml +46 -0
  12. data/config/disabled.yml +5 -0
  13. data/config/enabled.yml +322 -0
  14. data/lib/rubocop/cli.rb +248 -93
  15. data/lib/rubocop/config.rb +205 -0
  16. data/lib/rubocop/config_store.rb +37 -0
  17. data/lib/rubocop/cop/access_control.rb +41 -0
  18. data/lib/rubocop/cop/alias.rb +17 -0
  19. data/lib/rubocop/cop/align_parameters.rb +20 -95
  20. data/lib/rubocop/cop/and_or.rb +26 -0
  21. data/lib/rubocop/cop/ascii_comments.rb +13 -0
  22. data/lib/rubocop/cop/ascii_identifiers.rb +19 -0
  23. data/lib/rubocop/cop/avoid_class_vars.rb +15 -0
  24. data/lib/rubocop/cop/avoid_for.rb +17 -0
  25. data/lib/rubocop/cop/avoid_global_vars.rb +61 -0
  26. data/lib/rubocop/cop/avoid_perl_backrefs.rb +17 -0
  27. data/lib/rubocop/cop/avoid_perlisms.rb +47 -0
  28. data/lib/rubocop/cop/block_comments.rb +15 -0
  29. data/lib/rubocop/cop/blocks.rb +11 -47
  30. data/lib/rubocop/cop/case_indentation.rb +22 -0
  31. data/lib/rubocop/cop/class_and_module_camel_case.rb +20 -11
  32. data/lib/rubocop/cop/class_methods.rb +15 -0
  33. data/lib/rubocop/cop/collection_methods.rb +16 -16
  34. data/lib/rubocop/cop/colon_method_call.rb +20 -0
  35. data/lib/rubocop/cop/constant_name.rb +24 -0
  36. data/lib/rubocop/cop/cop.rb +34 -47
  37. data/lib/rubocop/cop/def_parentheses.rb +43 -35
  38. data/lib/rubocop/cop/empty_line_between_defs.rb +22 -0
  39. data/lib/rubocop/cop/empty_lines.rb +21 -13
  40. data/lib/rubocop/cop/empty_literal.rb +47 -0
  41. data/lib/rubocop/cop/encoding.rb +3 -3
  42. data/lib/rubocop/cop/end_of_line.rb +3 -3
  43. data/lib/rubocop/cop/ensure_return.rb +19 -0
  44. data/lib/rubocop/cop/eval.rb +19 -0
  45. data/lib/rubocop/cop/favor_join.rb +22 -0
  46. data/lib/rubocop/cop/favor_modifier.rb +38 -48
  47. data/lib/rubocop/cop/favor_percent_r.rb +19 -0
  48. data/lib/rubocop/cop/favor_sprintf.rb +21 -0
  49. data/lib/rubocop/cop/favor_unless_over_negated_if.rb +19 -17
  50. data/lib/rubocop/cop/handle_exceptions.rb +17 -0
  51. data/lib/rubocop/cop/hash_syntax.rb +29 -14
  52. data/lib/rubocop/cop/if_then_else.rb +32 -29
  53. data/lib/rubocop/cop/leading_comment_space.rb +17 -0
  54. data/lib/rubocop/cop/line_continuation.rb +15 -0
  55. data/lib/rubocop/cop/line_length.rb +4 -4
  56. data/lib/rubocop/cop/loop.rb +33 -0
  57. data/lib/rubocop/cop/method_and_variable_snake_case.rb +41 -17
  58. data/lib/rubocop/cop/method_length.rb +52 -0
  59. data/lib/rubocop/cop/new_lambda_literal.rb +8 -6
  60. data/lib/rubocop/cop/not.rb +21 -0
  61. data/lib/rubocop/cop/numeric_literals.rb +9 -7
  62. data/lib/rubocop/cop/offence.rb +12 -1
  63. data/lib/rubocop/cop/op_method.rb +26 -0
  64. data/lib/rubocop/cop/parameter_lists.rb +12 -6
  65. data/lib/rubocop/cop/parentheses_around_condition.rb +11 -11
  66. data/lib/rubocop/cop/percent_r.rb +19 -0
  67. data/lib/rubocop/cop/reduce_arguments.rb +29 -0
  68. data/lib/rubocop/cop/rescue_exception.rb +26 -0
  69. data/lib/rubocop/cop/rescue_modifier.rb +17 -0
  70. data/lib/rubocop/cop/semicolon.rb +31 -0
  71. data/lib/rubocop/cop/single_line_methods.rb +44 -0
  72. data/lib/rubocop/cop/space_after_comma_etc.rb +30 -10
  73. data/lib/rubocop/cop/space_after_control_keyword.rb +29 -0
  74. data/lib/rubocop/cop/string_literals.rb +9 -23
  75. data/lib/rubocop/cop/surrounding_space.rb +223 -83
  76. data/lib/rubocop/cop/symbol_array.rb +31 -0
  77. data/lib/rubocop/cop/symbol_name.rb +23 -0
  78. data/lib/rubocop/cop/syntax.rb +35 -5
  79. data/lib/rubocop/cop/tab.rb +3 -3
  80. data/lib/rubocop/cop/ternary_operator.rb +26 -24
  81. data/lib/rubocop/cop/trailing_whitespace.rb +3 -5
  82. data/lib/rubocop/cop/trivial_accessors.rb +26 -0
  83. data/lib/rubocop/cop/unless_else.rb +11 -7
  84. data/lib/rubocop/cop/util.rb +26 -0
  85. data/lib/rubocop/cop/variable_interpolation.rb +29 -0
  86. data/lib/rubocop/cop/when_then.rb +6 -14
  87. data/lib/rubocop/cop/word_array.rb +37 -0
  88. data/lib/rubocop/report/emacs_style.rb +2 -2
  89. data/lib/rubocop/report/plain_text.rb +1 -1
  90. data/lib/rubocop/version.rb +3 -1
  91. data/lib/rubocop.rb +48 -8
  92. data/rubocop.gemspec +32 -151
  93. data/spec/project_spec.rb +27 -0
  94. data/spec/rubocop/cli_spec.rb +573 -200
  95. data/spec/rubocop/config_spec.rb +409 -0
  96. data/spec/rubocop/config_store_spec.rb +66 -0
  97. data/spec/rubocop/cops/access_control_spec.rb +129 -0
  98. data/spec/rubocop/cops/alias_spec.rb +39 -0
  99. data/spec/rubocop/cops/align_parameters_spec.rb +66 -70
  100. data/spec/rubocop/cops/and_or_spec.rb +37 -0
  101. data/spec/rubocop/cops/ascii_comments_spec.rb +26 -0
  102. data/spec/rubocop/cops/ascii_identifiers_spec.rb +26 -0
  103. data/spec/rubocop/cops/avoid_class_vars_spec.rb +25 -0
  104. data/spec/rubocop/cops/avoid_for_spec.rb +35 -0
  105. data/spec/rubocop/cops/avoid_global_vars_spec.rb +32 -0
  106. data/spec/rubocop/cops/avoid_perl_backrefs_spec.rb +18 -0
  107. data/spec/rubocop/cops/avoid_perlisms_spec.rb +44 -0
  108. data/spec/rubocop/cops/block_comments_spec.rb +25 -0
  109. data/spec/rubocop/cops/blocks_spec.rb +33 -0
  110. data/spec/rubocop/cops/{indentation_spec.rb → case_indentation_spec.rb} +7 -7
  111. data/spec/rubocop/cops/class_and_module_camel_case_spec.rb +15 -5
  112. data/spec/rubocop/cops/class_methods_spec.rb +49 -0
  113. data/spec/rubocop/cops/collection_methods_spec.rb +9 -4
  114. data/spec/rubocop/cops/colon_method_call_spec.rb +53 -0
  115. data/spec/rubocop/cops/constant_name_spec.rb +42 -0
  116. data/spec/rubocop/cops/def_with_parentheses_spec.rb +13 -8
  117. data/spec/rubocop/cops/def_without_parentheses_spec.rb +11 -5
  118. data/spec/rubocop/cops/empty_line_between_defs_spec.rb +83 -0
  119. data/spec/rubocop/cops/empty_lines_spec.rb +14 -59
  120. data/spec/rubocop/cops/empty_literal_spec.rb +90 -0
  121. data/spec/rubocop/cops/encoding_spec.rb +11 -11
  122. data/spec/rubocop/cops/end_of_line_spec.rb +2 -2
  123. data/spec/rubocop/cops/ensure_return_spec.rb +35 -0
  124. data/spec/rubocop/cops/eval_spec.rb +39 -0
  125. data/spec/rubocop/cops/favor_join_spec.rb +35 -0
  126. data/spec/rubocop/cops/favor_modifier_spec.rb +16 -14
  127. data/spec/rubocop/cops/favor_percent_r_spec.rb +29 -0
  128. data/spec/rubocop/cops/favor_sprintf_spec.rb +51 -0
  129. data/spec/rubocop/cops/favor_unless_over_negated_if_spec.rb +4 -4
  130. data/spec/rubocop/cops/favor_until_over_negated_while_spec.rb +3 -3
  131. data/spec/rubocop/cops/handle_exceptions_spec.rb +34 -0
  132. data/spec/rubocop/cops/hash_syntax_spec.rb +11 -6
  133. data/spec/rubocop/cops/if_with_semicolon_spec.rb +7 -1
  134. data/spec/rubocop/cops/leading_comment_space_spec.rb +54 -0
  135. data/spec/rubocop/cops/line_continuation_spec.rb +24 -0
  136. data/spec/rubocop/cops/line_length_spec.rb +3 -2
  137. data/spec/rubocop/cops/loop_spec.rb +31 -0
  138. data/spec/rubocop/cops/method_and_variable_snake_case_spec.rb +55 -9
  139. data/spec/rubocop/cops/method_length_spec.rb +147 -0
  140. data/spec/rubocop/cops/multiline_if_then_spec.rb +15 -15
  141. data/spec/rubocop/cops/new_lambda_literal_spec.rb +5 -6
  142. data/spec/rubocop/cops/not_spec.rb +31 -0
  143. data/spec/rubocop/cops/numeric_literals_spec.rb +13 -13
  144. data/spec/rubocop/cops/offence_spec.rb +13 -0
  145. data/spec/rubocop/cops/one_line_conditional_spec.rb +1 -1
  146. data/spec/rubocop/cops/op_method_spec.rb +78 -0
  147. data/spec/rubocop/cops/parameter_lists_spec.rb +7 -7
  148. data/spec/rubocop/cops/parentheses_around_condition_spec.rb +41 -44
  149. data/spec/rubocop/cops/percent_r_spec.rb +29 -0
  150. data/spec/rubocop/cops/reduce_arguments_spec.rb +57 -0
  151. data/spec/rubocop/cops/rescue_exception_spec.rb +125 -0
  152. data/spec/rubocop/cops/rescue_modifier_spec.rb +37 -0
  153. data/spec/rubocop/cops/semicolon_spec.rb +88 -0
  154. data/spec/rubocop/cops/single_line_methods_spec.rb +50 -0
  155. data/spec/rubocop/cops/space_after_colon_spec.rb +3 -3
  156. data/spec/rubocop/cops/space_after_comma_spec.rb +14 -2
  157. data/spec/rubocop/cops/space_after_control_keyword_spec.rb +67 -0
  158. data/spec/rubocop/cops/space_after_semicolon_spec.rb +6 -1
  159. data/spec/rubocop/cops/space_around_braces_spec.rb +18 -3
  160. data/spec/rubocop/cops/space_around_equals_in_default_parameter_spec.rb +12 -2
  161. data/spec/rubocop/cops/space_around_operators_spec.rb +88 -26
  162. data/spec/rubocop/cops/space_inside_brackets_spec.rb +13 -7
  163. data/spec/rubocop/cops/space_inside_hash_literal_braces_spec.rb +79 -0
  164. data/spec/rubocop/cops/space_inside_parens_spec.rb +7 -3
  165. data/spec/rubocop/cops/string_literals_spec.rb +21 -6
  166. data/spec/rubocop/cops/symbol_array_spec.rb +41 -0
  167. data/spec/rubocop/cops/symbol_name_spec.rb +119 -0
  168. data/spec/rubocop/cops/syntax_spec.rb +28 -5
  169. data/spec/rubocop/cops/tab_spec.rb +2 -2
  170. data/spec/rubocop/cops/ternary_operator_spec.rb +13 -17
  171. data/spec/rubocop/cops/trailing_whitespace_spec.rb +3 -3
  172. data/spec/rubocop/cops/trivial_accessors_spec.rb +329 -0
  173. data/spec/rubocop/cops/unless_else_spec.rb +8 -8
  174. data/spec/rubocop/cops/variable_interpolation_spec.rb +49 -0
  175. data/spec/rubocop/cops/when_then_spec.rb +14 -14
  176. data/spec/rubocop/cops/word_array_spec.rb +47 -0
  177. data/spec/spec_helper.rb +30 -9
  178. data/spec/support/file_helper.rb +21 -0
  179. data/spec/support/isolated_environment.rb +27 -0
  180. metadata +235 -76
  181. data/.document +0 -5
  182. data/Gemfile.lock +0 -41
  183. data/VERSION +0 -1
  184. data/lib/rubocop/cop/ampersands_pipes_vs_and_or.rb +0 -25
  185. data/lib/rubocop/cop/grammar.rb +0 -135
  186. data/lib/rubocop/cop/indentation.rb +0 -44
  187. data/spec/rubocop/cops/ampersands_pipes_vs_and_or_spec.rb +0 -57
  188. data/spec/rubocop/cops/grammar_spec.rb +0 -71
  189. data/spec/rubocop/cops/multiline_blocks_spec.rb +0 -24
  190. data/spec/rubocop/cops/single_line_blocks_spec.rb +0 -22
@@ -3,22 +3,37 @@
3
3
  module Rubocop
4
4
  module Cop
5
5
  class HashSyntax < Cop
6
- ERROR_MESSAGE = 'Ruby 1.8 hash syntax detected'
7
-
8
- def inspect(file, source, tokens, sexp)
9
- each(:assoclist_from_args, sexp) do |assoclist_from_args|
10
- keys = assoclist_from_args[1].map { |assoc_new| assoc_new[1][0] }
11
- # If at least one of the keys in the hash is neither a symbol (:a)
12
- # nor a label (a:), we can't require the new syntax.
13
- return if keys.find do |key|
14
- not [:symbol_literal, :@label].include?(key)
6
+ MSG = 'Ruby 1.8 hash syntax detected'
7
+
8
+ def on_hash(node)
9
+ pairs = *node
10
+
11
+ sym_indices = pairs.all? { |p| word_symbol_pair?(p) }
12
+
13
+ if sym_indices
14
+ pairs.each do |pair|
15
+ if pair.loc.operator && pair.loc.operator.source == '=>'
16
+ add_offence(:convention,
17
+ pair.loc.line,
18
+ MSG)
19
+ end
15
20
  end
16
21
  end
17
- each(:assoc_new, sexp) do |assoc_new|
18
- if assoc_new[1][0] == :symbol_literal
19
- add_offence(:convention, assoc_new[1][1][1][-1].lineno,
20
- ERROR_MESSAGE)
21
- end
22
+
23
+ super
24
+ end
25
+
26
+ private
27
+
28
+ def word_symbol_pair?(pair)
29
+ key, _value = *pair
30
+
31
+ if key.type == :sym
32
+ sym_name = key.to_a[0]
33
+
34
+ sym_name =~ /\A\w+\z/
35
+ else
36
+ false
22
37
  end
23
38
  end
24
39
  end
@@ -3,43 +3,34 @@
3
3
  module Rubocop
4
4
  module Cop
5
5
  module IfThenElse
6
- def inspect(file, source, tokens, sexp)
7
- tokens.each_with_index do |t, ix|
8
- if t.type == :on_kw && ['if', 'unless'].include?(t.text)
9
- if kind_of_if(tokens, ix + 1) == self.class
10
- add_offence(:convention, t.pos.lineno, error_message)
11
- end
12
- end
13
- end
6
+ def on_if(node)
7
+ check(node)
8
+ super
9
+ end
10
+
11
+ def on_unless(node)
12
+ check(node)
13
+ super
14
14
  end
15
15
 
16
- def kind_of_if(tokens, ix)
17
- then_found = false
18
- tokens[ix..-1].each do |t|
19
- case t.type
20
- when :on_kw
21
- case t.text
22
- when 'then' then then_found = true
23
- when 'end' then return OneLineConditional
24
- end
25
- when :on_ignored_nl, :on_nl
26
- break
27
- when :on_semicolon
28
- return IfWithSemicolon
29
- when :on_comment
30
- break if t.text =~ /\n/
31
- when :on_sp
32
- nil
33
- else
34
- then_found = false
35
- end
16
+ def check(node)
17
+ # We won't check modifier or ternary conditionals.
18
+ if node.loc.expression.source =~ /\A(if|unless)\b/
19
+ line = offending_line(node)
20
+ add_offence(:convention, line, error_message) if line
36
21
  end
37
- then_found ? MultilineIfThen : nil
38
22
  end
39
23
  end
40
24
 
41
25
  class IfWithSemicolon < Cop
42
26
  include IfThenElse
27
+
28
+ def offending_line(node)
29
+ if node.loc.begin && node.loc.begin.source == ';'
30
+ node.loc.begin.line
31
+ end
32
+ end
33
+
43
34
  def error_message
44
35
  'Never use if x; Use the ternary operator instead.'
45
36
  end
@@ -47,6 +38,13 @@ module Rubocop
47
38
 
48
39
  class MultilineIfThen < Cop
49
40
  include IfThenElse
41
+
42
+ def offending_line(node)
43
+ if node.loc.expression.source =~ /\bthen\s*(#.*)?\s*$/
44
+ node.loc.begin.line
45
+ end
46
+ end
47
+
50
48
  def error_message
51
49
  'Never use then for multi-line if/unless.'
52
50
  end
@@ -54,6 +52,11 @@ module Rubocop
54
52
 
55
53
  class OneLineConditional < Cop
56
54
  include IfThenElse
55
+
56
+ def offending_line(node)
57
+ node.loc.expression.line unless node.loc.expression.source =~ /\n/
58
+ end
59
+
57
60
  def error_message
58
61
  'Favor the ternary operator (?:) over if/then/else/end constructs.'
59
62
  end
@@ -0,0 +1,17 @@
1
+ # encoding: utf-8
2
+
3
+ module Rubocop
4
+ module Cop
5
+ class LeadingCommentSpace < Cop
6
+ MSG = 'Missing space after #.'
7
+
8
+ def on_comment(c)
9
+ if c.text =~ /^#+[^#\s]/
10
+ unless c.text.start_with?('#!') && c.loc.line == 1
11
+ add_offence(:convention, c.loc.line, MSG)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,15 @@
1
+ # encoding: utf-8
2
+
3
+ module Rubocop
4
+ module Cop
5
+ class LineContinuation < Cop
6
+ MSG = 'Avoid the use of the line continuation character(\).'
7
+
8
+ def inspect(source, tokens, ast, comments)
9
+ source.each_with_index do |line, index|
10
+ add_offence(:convention, index, MSG) if line =~ /.*\\\z/
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -3,20 +3,20 @@
3
3
  module Rubocop
4
4
  module Cop
5
5
  class LineLength < Cop
6
- ERROR_MESSAGE = 'Line is too long. [%d/%d]'
6
+ MSG = 'Line is too long. [%d/%d]'
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
10
  max = LineLength.max
11
11
  if line.length > max
12
- message = sprintf(ERROR_MESSAGE, line.length, max)
12
+ message = sprintf(MSG, line.length, max)
13
13
  add_offence(:convention, index + 1, message)
14
14
  end
15
15
  end
16
16
  end
17
17
 
18
18
  def self.max
19
- LineLength.config ? LineLength.config['Max'] || 79 : 79
19
+ LineLength.config['Max']
20
20
  end
21
21
  end
22
22
  end
@@ -0,0 +1,33 @@
1
+ # encoding: utf-8
2
+
3
+ module Rubocop
4
+ module Cop
5
+ class Loop < Cop
6
+ MSG = 'Use Kernel#loop with break rather than begin/end/until(or while).'
7
+
8
+ def on_while(node)
9
+ check(node)
10
+
11
+ super
12
+ end
13
+
14
+ def on_until(node)
15
+ check(node)
16
+
17
+ super
18
+ end
19
+
20
+ private
21
+
22
+ def check(node)
23
+ _cond, body = *node
24
+ type = node.type.to_s
25
+
26
+ if body.type == :begin &&
27
+ !node.loc.expression.source.start_with?(type)
28
+ add_offence(:warning, node.loc.keyword.line, MSG)
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -3,28 +3,52 @@
3
3
  module Rubocop
4
4
  module Cop
5
5
  class MethodAndVariableSnakeCase < Cop
6
- ERROR_MESSAGE = 'Use snake_case for methods and variables.'
6
+ MSG = 'Use snake_case for methods and variables.'
7
7
  SNAKE_CASE = /^@?[\da-z_]+[!?=]?$/
8
8
 
9
- def inspect(file, source, tokens, sexp)
10
- each(:def, sexp) { |s| check(s[1]) }
11
-
12
- each(:assign, sexp) do |s|
13
- case s[1][0]
14
- when :var_field
15
- check(s[1][1])
16
- when :field
17
- if s[1][1][0] == :var_ref && s[1][1][1][0..1] == [:@kw, 'self']
18
- check(s[1][3])
19
- end
20
- end
9
+ # http://phrogz.net/programmingruby/language.html#table_18.4
10
+ OPERATOR_METHODS = %w(
11
+ | ^ & <=> == === =~ > >= < <= << >>
12
+ + - * / % ** ~ +@ -@ [] []= ` ! != !~
13
+ ).map(&:to_sym)
14
+
15
+ def inspect(source, tokens, node, comments)
16
+ on_node([:def, :defs, :lvasgn, :ivasgn, :send], node) do |n|
17
+ name = case n.type
18
+ when :def
19
+ name_of_instance_method(n)
20
+ when :defs
21
+ name_of_singleton_method(n)
22
+ when :lvasgn, :ivasgn
23
+ name_of_variable(n)
24
+ when :send
25
+ name_of_setter(n)
26
+ end
27
+
28
+ next unless name
29
+ next if name =~ SNAKE_CASE || OPERATOR_METHODS.include?(name)
30
+
31
+ add_offence(:convention, n.location.line, MSG)
21
32
  end
22
33
  end
23
34
 
24
- def check(sexp)
25
- if [:@ivar, :@ident].include?(sexp[0]) && sexp[1] !~ SNAKE_CASE
26
- add_offence(:convention, sexp[2].lineno, ERROR_MESSAGE)
27
- end
35
+ def name_of_instance_method(def_node)
36
+ def_node.children.first
37
+ end
38
+
39
+ def name_of_singleton_method(defs_node)
40
+ defs_node.children[1]
41
+ end
42
+
43
+ def name_of_variable(vasgn_node)
44
+ vasgn_node.children.first
45
+ end
46
+
47
+ def name_of_setter(send_node)
48
+ receiver, method_name = *send_node
49
+ return nil unless receiver && receiver.type == :self
50
+ return nil unless method_name.to_s.end_with?('=')
51
+ method_name
28
52
  end
29
53
  end
30
54
  end
@@ -0,0 +1,52 @@
1
+ # encoding: utf-8
2
+
3
+ module Rubocop
4
+ module Cop
5
+ class MethodLength < Cop
6
+ MSG = 'Method has too many lines. [%d/%d]'
7
+
8
+ def on_def(node)
9
+ check(node)
10
+
11
+ super
12
+ end
13
+
14
+ def on_defs(node)
15
+ check(node)
16
+
17
+ super
18
+ end
19
+
20
+ def max_length
21
+ MethodLength.config['Max']
22
+ end
23
+
24
+ def count_comments?
25
+ MethodLength.config['CountComments']
26
+ end
27
+
28
+ private
29
+
30
+ def check(node)
31
+ method_length = calculate_length(node.loc.expression.source)
32
+
33
+ if method_length > max_length
34
+ message = sprintf(MSG, method_length, max_length)
35
+ add_offence(:convention, node.loc.keyword.line, message)
36
+ end
37
+ end
38
+
39
+ def calculate_length(source)
40
+ lines = source.lines.to_a[1...-1]
41
+
42
+ return 0 unless lines
43
+
44
+ lines.map!(&:strip).reject!(&:empty?)
45
+
46
+ lines.reject! { |line| line =~ /^\s*#/ } unless count_comments?
47
+
48
+ lines.size
49
+ end
50
+ end
51
+ end
52
+ end
@@ -3,14 +3,16 @@
3
3
  module Rubocop
4
4
  module Cop
5
5
  class NewLambdaLiteral < Cop
6
- ERROR_MESSAGE = 'The new lambda literal syntax is preferred in Ruby 1.9.'
6
+ MSG = 'Use the new lambda literal syntax ->(params) {...}.'
7
7
 
8
- def inspect(file, source, tokens, sexp)
9
- each(:fcall, sexp) do |s|
10
- if s[1][0..1] == [:@ident, 'lambda']
11
- add_offence(:convention, s[1][-1].lineno, ERROR_MESSAGE)
12
- end
8
+ TARGET = s(:send, nil, :lambda)
9
+
10
+ def on_send(node)
11
+ if node == TARGET && node.loc.selector.source != '->'
12
+ add_offence(:convention, node.loc.line, MSG)
13
13
  end
14
+
15
+ super
14
16
  end
15
17
  end
16
18
  end
@@ -0,0 +1,21 @@
1
+ # encoding: utf-8
2
+
3
+ module Rubocop
4
+ module Cop
5
+ class Not < Cop
6
+ MSG = 'Use ! instead of not.'
7
+
8
+ def on_send(node)
9
+ _receiver, method_name, *args = *node
10
+
11
+ # not does not take any arguments
12
+ if args.empty? && method_name == :! &&
13
+ node.loc.selector.source == 'not'
14
+ add_offence(:convention, node.loc.line, MSG)
15
+ end
16
+
17
+ super
18
+ end
19
+ end
20
+ end
21
+ end
@@ -3,17 +3,19 @@
3
3
  module Rubocop
4
4
  module Cop
5
5
  class NumericLiterals < Cop
6
- ERROR_MESSAGE = 'Add underscores to large numeric literals to ' +
6
+ MSG = 'Add underscores to large numeric literals to ' +
7
7
  'improve their readability.'
8
8
 
9
- def inspect(file, source, tokens, sexp)
10
- tokens.each do |t|
11
- if [:on_int, :on_float].include?(t.type) &&
12
- t.text.split('.').grep(/\d{6}/).any?
13
- add_offence(:convention, t.pos.lineno, ERROR_MESSAGE)
14
- end
9
+ def on_int(node)
10
+ value, = *node
11
+
12
+ if value > 10000 &&
13
+ node.loc.expression.source.split('.').grep(/\d{6}/).any?
14
+ add_offence(:convention, node.loc.expression.line, MSG)
15
15
  end
16
16
  end
17
+
18
+ alias_method :on_float, :on_int
17
19
  end
18
20
  end
19
21
  end
@@ -14,12 +14,23 @@ module Rubocop
14
14
  end
15
15
 
16
16
  def to_s
17
- "#{encode_severity}:%3d: #{message}" % [line_number]
17
+ # we must be wary of messages containing % in them
18
+ sprintf("#{encode_severity}:%3d: #{message.gsub(/%/, '%%')}",
19
+ line_number)
18
20
  end
19
21
 
20
22
  def encode_severity
21
23
  @severity.to_s[0].upcase
22
24
  end
25
+
26
+ def ==(other)
27
+ severity == other.severity && line_number == other.line_number &&
28
+ message == other.message
29
+ end
30
+
31
+ def explode
32
+ [severity, line_number, message]
33
+ end
23
34
  end
24
35
  end
25
36
  end
@@ -0,0 +1,26 @@
1
+ # encoding: utf-8
2
+
3
+ module Rubocop
4
+ module Cop
5
+ class OpMethod < Cop
6
+ MSG = 'When defining the %s operator, name its argument other.'
7
+
8
+ BLACKLISTED = [:+@, :-@, :[], :[]=, :<<]
9
+
10
+ TARGET_ARGS = s(:args, s(:arg, :other))
11
+
12
+ def on_def(node)
13
+ name, args, _body = *node
14
+
15
+ if name !~ /\A\w/ && !BLACKLISTED.include?(name) &&
16
+ args.children.size == 1 && args != TARGET_ARGS
17
+ add_offence(:convention,
18
+ node.loc.line,
19
+ sprintf(MSG, name))
20
+ end
21
+
22
+ super
23
+ end
24
+ end
25
+ end
26
+ end
@@ -3,14 +3,20 @@
3
3
  module Rubocop
4
4
  module Cop
5
5
  class ParameterLists < Cop
6
- ERROR_MESSAGE = 'Avoid parameter lists longer than four parameters.'
6
+ MSG = 'Avoid parameter lists longer than %d parameters.'
7
7
 
8
- def inspect(file, source, tokens, sexp)
9
- each(:params, sexp) do |params|
10
- if params[1] && params[1].size > 4
11
- add_offence(:convention, params[1][0][-1].lineno, ERROR_MESSAGE)
12
- end
8
+ def on_args(node)
9
+ args_count = node.children.size
10
+
11
+ if args_count > max_params
12
+ add_offence(:convention, node.loc.line, sprintf(MSG, max_params))
13
13
  end
14
+
15
+ super
16
+ end
17
+
18
+ def max_params
19
+ ParameterLists.config['Max']
14
20
  end
15
21
  end
16
22
  end
@@ -3,19 +3,19 @@
3
3
  module Rubocop
4
4
  module Cop
5
5
  class ParenthesesAroundCondition < Cop
6
- ERROR_MESSAGE = "Don't use parentheses around the condition of an " +
6
+ MSG = "Don't use parentheses around the condition of an " +
7
7
  'if/unless/while/until, unless the condition contains an assignment.'
8
8
 
9
- def inspect(file, source, tokens, sexp)
10
- [:if, :elsif, :unless, :while, :until,
11
- :if_mod, :unless_mod, :while_mod, :until_mod].each do |keyword|
12
- each(keyword, sexp) do |s|
13
- if s[1][0] == :paren && s[1][1][0][0] != :assign
14
- positions = all_positions(s[1])
15
- if positions.first.lineno == positions.last.lineno
16
- add_offence(:convention, positions.first.lineno, ERROR_MESSAGE)
17
- end
18
- end
9
+ def inspect(source, tokens, ast, comments)
10
+ on_node([:if, :while, :until], ast) do |node|
11
+ cond, _body = *node
12
+
13
+ cond_source = cond.loc.expression.source
14
+
15
+ if cond_source.start_with?('(') && cond_source.end_with?(')')
16
+ add_offence(:convetion,
17
+ cond.loc.line,
18
+ MSG)
19
19
  end
20
20
  end
21
21
  end
@@ -0,0 +1,19 @@
1
+ # encoding: utf-8
2
+
3
+ module Rubocop
4
+ module Cop
5
+ class PercentR < Cop
6
+ MSG = 'Use %r only for regular expressions matching more ' +
7
+ "than one '/' character."
8
+
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)
13
+ end
14
+
15
+ super
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,29 @@
1
+ # encoding: utf-8
2
+
3
+ module Rubocop
4
+ module Cop
5
+ class ReduceArguments < Cop
6
+ MSG = 'Name reduce arguments |a, e| (accumulator, element)'
7
+
8
+ ARGS_NODE = s(:args, s(:arg, :a), s(:arg, :e))
9
+
10
+ def on_block(node)
11
+ # we care only for single line blocks
12
+ return unless Util.block_length(node) == 0
13
+
14
+ method_node, args_node, _body_node = *node
15
+ receiver, method_name, _method_args = *method_node
16
+
17
+ # discard other scenarios
18
+ return unless receiver
19
+ return unless [:reduce, :inject].include?(method_name)
20
+
21
+ unless args_node == ARGS_NODE
22
+ add_offence(:convention, node.loc.line, MSG)
23
+ end
24
+
25
+ super
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,26 @@
1
+ # encoding: utf-8
2
+
3
+ module Rubocop
4
+ module Cop
5
+ class RescueException < Cop
6
+ MSG = 'Avoid rescuing the Exception class.'
7
+
8
+ def on_resbody(node)
9
+ return unless node.children.first
10
+ rescue_args = node.children.first.children
11
+ if rescue_args.any? { |a| targets_exception?(a) }
12
+ add_offence(:warning, node.location.line, MSG)
13
+ end
14
+
15
+ super
16
+ end
17
+
18
+ def targets_exception?(rescue_arg_node)
19
+ return false unless rescue_arg_node.type == :const
20
+ namespace, klass_name = *rescue_arg_node
21
+ return false unless namespace.nil? || namespace.type == :cbase
22
+ klass_name == :Exception
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,17 @@
1
+ # encoding: utf-8
2
+
3
+ module Rubocop
4
+ module Cop
5
+ class RescueModifier < Cop
6
+ MSG = 'Avoid using rescue in its modifier form.'
7
+
8
+ def inspect(source, tokens, ast, comments)
9
+ on_node(:rescue, ast, :begin) do |s|
10
+ add_offence(:convention,
11
+ s.loc.line,
12
+ MSG)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,31 @@
1
+ # encoding: utf-8
2
+
3
+ module Rubocop
4
+ module Cop
5
+ class Semicolon < Cop
6
+ MSG = 'Do not use semicolons to terminate expressions.'
7
+
8
+ def inspect(source, tokens, ast, comments)
9
+ on_node(:begin, ast) do |node|
10
+ exprs = node.children
11
+
12
+ next if exprs.size < 2
13
+
14
+ # create a map matching lines to the number of expressions on them
15
+ exprs_lines = exprs.map { |e| e.loc.expression.line }
16
+ lines = exprs_lines.group_by { |i| i }
17
+
18
+ # every line with more than 1 expression on it is an offence
19
+ lines.each do |line, expr_on_line|
20
+ add_offence(:convention, line, MSG) if expr_on_line.size > 1
21
+ end
22
+ end
23
+
24
+ # not pretty reliable, but the best we can do for now
25
+ source.each_with_index do |line, index|
26
+ add_offence(:convention, index, MSG) if line =~ /;\s*\z/
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end