sabat-rubocop 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (239) hide show
  1. data/.gitignore +50 -0
  2. data/.rspec +1 -0
  3. data/.rubocop.yml +7 -0
  4. data/.travis.yml +7 -0
  5. data/.yardopts +2 -0
  6. data/CHANGELOG.md +268 -0
  7. data/CONTRIBUTING.md +16 -0
  8. data/Gemfile +7 -0
  9. data/LICENSE.txt +20 -0
  10. data/README.md +324 -0
  11. data/Rakefile +29 -0
  12. data/bin/rubocop +22 -0
  13. data/config/default.yml +58 -0
  14. data/config/disabled.yml +5 -0
  15. data/config/enabled.yml +403 -0
  16. data/lib/rubocop.rb +116 -0
  17. data/lib/rubocop/cli.rb +407 -0
  18. data/lib/rubocop/config.rb +250 -0
  19. data/lib/rubocop/config_store.rb +39 -0
  20. data/lib/rubocop/cop/cop.rb +138 -0
  21. data/lib/rubocop/cop/lint/assignment_in_condition.rb +54 -0
  22. data/lib/rubocop/cop/lint/end_alignment.rb +189 -0
  23. data/lib/rubocop/cop/lint/end_in_method.rb +30 -0
  24. data/lib/rubocop/cop/lint/ensure_return.rb +22 -0
  25. data/lib/rubocop/cop/lint/eval.rb +22 -0
  26. data/lib/rubocop/cop/lint/handle_exceptions.rb +20 -0
  27. data/lib/rubocop/cop/lint/literal_in_condition.rb +81 -0
  28. data/lib/rubocop/cop/lint/loop.rb +29 -0
  29. data/lib/rubocop/cop/lint/rescue_exception.rb +29 -0
  30. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +34 -0
  31. data/lib/rubocop/cop/lint/unreachable_code.rb +35 -0
  32. data/lib/rubocop/cop/lint/unused_local_variable.rb +32 -0
  33. data/lib/rubocop/cop/lint/void.rb +58 -0
  34. data/lib/rubocop/cop/offence.rb +136 -0
  35. data/lib/rubocop/cop/rails/validation.rb +30 -0
  36. data/lib/rubocop/cop/style/access_control.rb +58 -0
  37. data/lib/rubocop/cop/style/alias.rb +28 -0
  38. data/lib/rubocop/cop/style/align_parameters.rb +39 -0
  39. data/lib/rubocop/cop/style/and_or.rb +45 -0
  40. data/lib/rubocop/cop/style/ascii_comments.rb +21 -0
  41. data/lib/rubocop/cop/style/ascii_identifiers.rb +22 -0
  42. data/lib/rubocop/cop/style/attr.rb +20 -0
  43. data/lib/rubocop/cop/style/avoid_class_vars.rb +20 -0
  44. data/lib/rubocop/cop/style/avoid_for.rb +18 -0
  45. data/lib/rubocop/cop/style/avoid_global_vars.rb +65 -0
  46. data/lib/rubocop/cop/style/avoid_perl_backrefs.rb +21 -0
  47. data/lib/rubocop/cop/style/avoid_perlisms.rb +50 -0
  48. data/lib/rubocop/cop/style/begin_block.rb +18 -0
  49. data/lib/rubocop/cop/style/block_comments.rb +20 -0
  50. data/lib/rubocop/cop/style/block_nesting.rb +47 -0
  51. data/lib/rubocop/cop/style/blocks.rb +27 -0
  52. data/lib/rubocop/cop/style/case_equality.rb +22 -0
  53. data/lib/rubocop/cop/style/case_indentation.rb +28 -0
  54. data/lib/rubocop/cop/style/character_literal.rb +37 -0
  55. data/lib/rubocop/cop/style/class_and_module_camel_case.rb +33 -0
  56. data/lib/rubocop/cop/style/class_methods.rb +22 -0
  57. data/lib/rubocop/cop/style/collection_methods.rb +56 -0
  58. data/lib/rubocop/cop/style/colon_method_call.rb +29 -0
  59. data/lib/rubocop/cop/style/constant_name.rb +31 -0
  60. data/lib/rubocop/cop/style/def_parentheses.rb +70 -0
  61. data/lib/rubocop/cop/style/documentation.rb +58 -0
  62. data/lib/rubocop/cop/style/dot_position.rb +25 -0
  63. data/lib/rubocop/cop/style/empty_line_between_defs.rb +26 -0
  64. data/lib/rubocop/cop/style/empty_lines.rb +40 -0
  65. data/lib/rubocop/cop/style/empty_literal.rb +53 -0
  66. data/lib/rubocop/cop/style/encoding.rb +29 -0
  67. data/lib/rubocop/cop/style/end_block.rb +18 -0
  68. data/lib/rubocop/cop/style/end_of_line.rb +23 -0
  69. data/lib/rubocop/cop/style/favor_join.rb +29 -0
  70. data/lib/rubocop/cop/style/favor_modifier.rb +118 -0
  71. data/lib/rubocop/cop/style/favor_sprintf.rb +28 -0
  72. data/lib/rubocop/cop/style/favor_unless_over_negated_if.rb +54 -0
  73. data/lib/rubocop/cop/style/hash_syntax.rb +47 -0
  74. data/lib/rubocop/cop/style/if_then_else.rb +29 -0
  75. data/lib/rubocop/cop/style/if_with_semicolon.rb +20 -0
  76. data/lib/rubocop/cop/style/lambda.rb +47 -0
  77. data/lib/rubocop/cop/style/leading_comment_space.rb +25 -0
  78. data/lib/rubocop/cop/style/line_continuation.rb +26 -0
  79. data/lib/rubocop/cop/style/line_length.rb +30 -0
  80. data/lib/rubocop/cop/style/method_and_variable_snake_case.rb +61 -0
  81. data/lib/rubocop/cop/style/method_call_parentheses.rb +22 -0
  82. data/lib/rubocop/cop/style/method_length.rb +57 -0
  83. data/lib/rubocop/cop/style/multiline_if_then.rb +47 -0
  84. data/lib/rubocop/cop/style/not.rb +24 -0
  85. data/lib/rubocop/cop/style/numeric_literals.rb +25 -0
  86. data/lib/rubocop/cop/style/one_line_conditional.rb +20 -0
  87. data/lib/rubocop/cop/style/op_method.rb +29 -0
  88. data/lib/rubocop/cop/style/parameter_lists.rb +42 -0
  89. data/lib/rubocop/cop/style/parentheses_around_condition.rb +42 -0
  90. data/lib/rubocop/cop/style/proc.rb +30 -0
  91. data/lib/rubocop/cop/style/reduce_arguments.rb +34 -0
  92. data/lib/rubocop/cop/style/regexp_literal.rb +39 -0
  93. data/lib/rubocop/cop/style/rescue_modifier.rb +55 -0
  94. data/lib/rubocop/cop/style/semicolon.rb +51 -0
  95. data/lib/rubocop/cop/style/single_line_methods.rb +48 -0
  96. data/lib/rubocop/cop/style/space_after_comma_etc.rb +69 -0
  97. data/lib/rubocop/cop/style/space_after_control_keyword.rb +32 -0
  98. data/lib/rubocop/cop/style/string_literals.rb +36 -0
  99. data/lib/rubocop/cop/style/surrounding_space.rb +314 -0
  100. data/lib/rubocop/cop/style/symbol_array.rb +31 -0
  101. data/lib/rubocop/cop/style/symbol_name.rb +27 -0
  102. data/lib/rubocop/cop/style/tab.rb +25 -0
  103. data/lib/rubocop/cop/style/ternary_operator.rb +49 -0
  104. data/lib/rubocop/cop/style/trailing_whitespace.rb +24 -0
  105. data/lib/rubocop/cop/style/trivial_accessors.rb +32 -0
  106. data/lib/rubocop/cop/style/unless_else.rb +26 -0
  107. data/lib/rubocop/cop/style/variable_interpolation.rb +32 -0
  108. data/lib/rubocop/cop/style/when_then.rb +25 -0
  109. data/lib/rubocop/cop/style/while_until_do.rb +45 -0
  110. data/lib/rubocop/cop/style/word_array.rb +44 -0
  111. data/lib/rubocop/cop/util.rb +27 -0
  112. data/lib/rubocop/cop/variable_inspector.rb +280 -0
  113. data/lib/rubocop/formatter/base_formatter.rb +119 -0
  114. data/lib/rubocop/formatter/clang_style_formatter.rb +21 -0
  115. data/lib/rubocop/formatter/emacs_style_formatter.rb +17 -0
  116. data/lib/rubocop/formatter/formatter_set.rb +77 -0
  117. data/lib/rubocop/formatter/json_formatter.rb +76 -0
  118. data/lib/rubocop/formatter/progress_formatter.rb +63 -0
  119. data/lib/rubocop/formatter/simple_text_formatter.rb +62 -0
  120. data/lib/rubocop/version.rb +21 -0
  121. data/rubocop.gemspec +36 -0
  122. data/spec/.rubocop.yml +5 -0
  123. data/spec/project_spec.rb +24 -0
  124. data/spec/rubocop/cli_spec.rb +906 -0
  125. data/spec/rubocop/config_spec.rb +470 -0
  126. data/spec/rubocop/config_store_spec.rb +66 -0
  127. data/spec/rubocop/cops/cop_spec.rb +38 -0
  128. data/spec/rubocop/cops/lint/assignment_in_condition_spec.rb +111 -0
  129. data/spec/rubocop/cops/lint/end_alignment_spec.rb +333 -0
  130. data/spec/rubocop/cops/lint/end_in_method_spec.rb +35 -0
  131. data/spec/rubocop/cops/lint/ensure_return_spec.rb +37 -0
  132. data/spec/rubocop/cops/lint/eval_spec.rb +41 -0
  133. data/spec/rubocop/cops/lint/handle_exceptions_spec.rb +36 -0
  134. data/spec/rubocop/cops/lint/literal_in_condition_spec.rb +42 -0
  135. data/spec/rubocop/cops/lint/loop_spec.rb +33 -0
  136. data/spec/rubocop/cops/lint/rescue_exception_spec.rb +127 -0
  137. data/spec/rubocop/cops/lint/shadowing_outer_local_variable_spec.rb +243 -0
  138. data/spec/rubocop/cops/lint/unreachable_code_spec.rb +69 -0
  139. data/spec/rubocop/cops/lint/unused_local_variable_spec.rb +497 -0
  140. data/spec/rubocop/cops/lint/void_spec.rb +63 -0
  141. data/spec/rubocop/cops/offence_spec.rb +133 -0
  142. data/spec/rubocop/cops/rails/validation_spec.rb +27 -0
  143. data/spec/rubocop/cops/style/access_control_spec.rb +142 -0
  144. data/spec/rubocop/cops/style/alias_spec.rb +47 -0
  145. data/spec/rubocop/cops/style/align_parameters_spec.rb +199 -0
  146. data/spec/rubocop/cops/style/and_or_spec.rb +39 -0
  147. data/spec/rubocop/cops/style/ascii_comments_spec.rb +28 -0
  148. data/spec/rubocop/cops/style/ascii_identifiers_spec.rb +28 -0
  149. data/spec/rubocop/cops/style/attr_spec.rb +20 -0
  150. data/spec/rubocop/cops/style/avoid_class_vars_spec.rb +27 -0
  151. data/spec/rubocop/cops/style/avoid_for_spec.rb +37 -0
  152. data/spec/rubocop/cops/style/avoid_global_vars_spec.rb +34 -0
  153. data/spec/rubocop/cops/style/avoid_perl_backrefs_spec.rb +20 -0
  154. data/spec/rubocop/cops/style/avoid_perlisms_spec.rb +47 -0
  155. data/spec/rubocop/cops/style/begin_block_spec.rb +19 -0
  156. data/spec/rubocop/cops/style/block_comments_spec.rb +27 -0
  157. data/spec/rubocop/cops/style/block_nesting_spec.rb +159 -0
  158. data/spec/rubocop/cops/style/blocks_spec.rb +35 -0
  159. data/spec/rubocop/cops/style/case_equality_spec.rb +18 -0
  160. data/spec/rubocop/cops/style/case_indentation_spec.rb +88 -0
  161. data/spec/rubocop/cops/style/character_literal_spec.rb +28 -0
  162. data/spec/rubocop/cops/style/class_and_module_camel_case_spec.rb +46 -0
  163. data/spec/rubocop/cops/style/class_methods_spec.rb +51 -0
  164. data/spec/rubocop/cops/style/collection_methods_spec.rb +41 -0
  165. data/spec/rubocop/cops/style/colon_method_call_spec.rb +55 -0
  166. data/spec/rubocop/cops/style/constant_name_spec.rb +56 -0
  167. data/spec/rubocop/cops/style/def_with_parentheses_spec.rb +40 -0
  168. data/spec/rubocop/cops/style/def_without_parentheses_spec.rb +34 -0
  169. data/spec/rubocop/cops/style/documentation_spec.rb +79 -0
  170. data/spec/rubocop/cops/style/dot_position_spec.rb +30 -0
  171. data/spec/rubocop/cops/style/empty_line_between_defs_spec.rb +85 -0
  172. data/spec/rubocop/cops/style/empty_lines_spec.rb +40 -0
  173. data/spec/rubocop/cops/style/empty_literal_spec.rb +91 -0
  174. data/spec/rubocop/cops/style/encoding_spec.rb +49 -0
  175. data/spec/rubocop/cops/style/end_block_spec.rb +19 -0
  176. data/spec/rubocop/cops/style/end_of_line_spec.rb +25 -0
  177. data/spec/rubocop/cops/style/favor_join_spec.rb +37 -0
  178. data/spec/rubocop/cops/style/favor_modifier_spec.rb +160 -0
  179. data/spec/rubocop/cops/style/favor_sprintf_spec.rb +53 -0
  180. data/spec/rubocop/cops/style/favor_unless_over_negated_if_spec.rb +64 -0
  181. data/spec/rubocop/cops/style/favor_until_over_negated_while_spec.rb +47 -0
  182. data/spec/rubocop/cops/style/hash_syntax_spec.rb +51 -0
  183. data/spec/rubocop/cops/style/if_with_semicolon_spec.rb +25 -0
  184. data/spec/rubocop/cops/style/lambda_spec.rb +45 -0
  185. data/spec/rubocop/cops/style/leading_comment_space_spec.rb +65 -0
  186. data/spec/rubocop/cops/style/line_continuation_spec.rb +26 -0
  187. data/spec/rubocop/cops/style/line_length_spec.rb +25 -0
  188. data/spec/rubocop/cops/style/method_and_variable_snake_case_spec.rb +95 -0
  189. data/spec/rubocop/cops/style/method_call_parentheses_spec.rb +25 -0
  190. data/spec/rubocop/cops/style/method_length_spec.rb +151 -0
  191. data/spec/rubocop/cops/style/multiline_if_then_spec.rb +97 -0
  192. data/spec/rubocop/cops/style/not_spec.rb +28 -0
  193. data/spec/rubocop/cops/style/numeric_literals_spec.rb +51 -0
  194. data/spec/rubocop/cops/style/one_line_conditional_spec.rb +18 -0
  195. data/spec/rubocop/cops/style/op_method_spec.rb +80 -0
  196. data/spec/rubocop/cops/style/parameter_lists_spec.rb +49 -0
  197. data/spec/rubocop/cops/style/parentheses_around_condition_spec.rb +59 -0
  198. data/spec/rubocop/cops/style/proc_spec.rb +28 -0
  199. data/spec/rubocop/cops/style/reduce_arguments_spec.rb +59 -0
  200. data/spec/rubocop/cops/style/regexp_literal_spec.rb +83 -0
  201. data/spec/rubocop/cops/style/rescue_modifier_spec.rb +122 -0
  202. data/spec/rubocop/cops/style/semicolon_spec.rb +95 -0
  203. data/spec/rubocop/cops/style/single_line_methods_spec.rb +54 -0
  204. data/spec/rubocop/cops/style/space_after_colon_spec.rb +29 -0
  205. data/spec/rubocop/cops/style/space_after_comma_spec.rb +31 -0
  206. data/spec/rubocop/cops/style/space_after_control_keyword_spec.rb +69 -0
  207. data/spec/rubocop/cops/style/space_after_semicolon_spec.rb +24 -0
  208. data/spec/rubocop/cops/style/space_around_braces_spec.rb +49 -0
  209. data/spec/rubocop/cops/style/space_around_equals_in_default_parameter_spec.rb +34 -0
  210. data/spec/rubocop/cops/style/space_around_operators_spec.rb +216 -0
  211. data/spec/rubocop/cops/style/space_inside_brackets_spec.rb +51 -0
  212. data/spec/rubocop/cops/style/space_inside_hash_literal_braces_spec.rb +99 -0
  213. data/spec/rubocop/cops/style/space_inside_parens_spec.rb +33 -0
  214. data/spec/rubocop/cops/style/string_literals_spec.rb +62 -0
  215. data/spec/rubocop/cops/style/symbol_array_spec.rb +45 -0
  216. data/spec/rubocop/cops/style/symbol_name_spec.rb +122 -0
  217. data/spec/rubocop/cops/style/tab_spec.rb +23 -0
  218. data/spec/rubocop/cops/style/ternary_operator_spec.rb +42 -0
  219. data/spec/rubocop/cops/style/trailing_whitespace_spec.rb +29 -0
  220. data/spec/rubocop/cops/style/trivial_accessors_spec.rb +338 -0
  221. data/spec/rubocop/cops/style/unless_else_spec.rb +31 -0
  222. data/spec/rubocop/cops/style/variable_interpolation_spec.rb +53 -0
  223. data/spec/rubocop/cops/style/when_then_spec.rb +40 -0
  224. data/spec/rubocop/cops/style/while_until_do_spec.rb +47 -0
  225. data/spec/rubocop/cops/style/word_array_spec.rb +61 -0
  226. data/spec/rubocop/cops/variable_inspector_spec.rb +374 -0
  227. data/spec/rubocop/formatter/base_formatter_spec.rb +190 -0
  228. data/spec/rubocop/formatter/clang_style_formatter_spec.rb +70 -0
  229. data/spec/rubocop/formatter/emacs_style_formatter_spec.rb +32 -0
  230. data/spec/rubocop/formatter/formatter_set_spec.rb +132 -0
  231. data/spec/rubocop/formatter/json_formatter_spec.rb +142 -0
  232. data/spec/rubocop/formatter/progress_formatter_spec.rb +196 -0
  233. data/spec/rubocop/formatter/simple_text_formatter_spec.rb +74 -0
  234. data/spec/spec_helper.rb +92 -0
  235. data/spec/support/file_helper.rb +21 -0
  236. data/spec/support/isolated_environment.rb +27 -0
  237. data/spec/support/mri_syntax_checker.rb +69 -0
  238. data/spec/support/shared_examples.rb +33 -0
  239. metadata +517 -0
@@ -0,0 +1,30 @@
1
+ # encoding: utf-8
2
+
3
+ module Rubocop
4
+ module Cop
5
+ module Style
6
+ # This cops checks for uses of Proc.new where Kernel#proc
7
+ # would be more appropriate.
8
+ class Proc < Cop
9
+ MSG = 'Use proc instead of Proc.new.'
10
+
11
+ TARGET = s(:send, s(:const, nil, :Proc), :new)
12
+
13
+ def on_block(node)
14
+ # We're looking for
15
+ # (block
16
+ # (send
17
+ # (const nil :Proc) :new)
18
+ # ...)
19
+ block_method, = *node
20
+
21
+ if block_method == TARGET
22
+ add_offence(:convention, block_method.loc.expression, MSG)
23
+ end
24
+
25
+ super
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,34 @@
1
+ # encoding: utf-8
2
+
3
+ module Rubocop
4
+ module Cop
5
+ module Style
6
+ # This cop checks whether the block arguments of a single-line
7
+ # reduce(inject) call are named *a*(for accumulator) and *e*
8
+ # (for element)
9
+ class ReduceArguments < Cop
10
+ MSG = 'Name reduce arguments |a, e| (accumulator, element).'
11
+
12
+ ARGS_NODE = s(:args, s(:arg, :a), s(:arg, :e))
13
+
14
+ def on_block(node)
15
+ # we care only for single line blocks
16
+ return unless Util.block_length(node) == 0
17
+
18
+ method_node, args_node, _body_node = *node
19
+ receiver, method_name, _method_args = *method_node
20
+
21
+ # discard other scenarios
22
+ return unless receiver
23
+ return unless [:reduce, :inject].include?(method_name)
24
+
25
+ unless args_node == ARGS_NODE
26
+ add_offence(:convention, node.loc.expression, MSG)
27
+ end
28
+
29
+ super
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,39 @@
1
+ # encoding: utf-8
2
+
3
+ module Rubocop
4
+ module Cop
5
+ module Style
6
+ # This cop checks for regexp literals and reports offences based
7
+ # on how many escaped slashes there are in the regexp and on the
8
+ # value of the configuration parameter MaxSlashes.
9
+ class RegexpLiteral < Cop
10
+ def on_regexp(node)
11
+ slashes = node.loc.expression.source[1...-1].scan(/\//).size
12
+ max = RegexpLiteral.max_slashes
13
+ msg = if node.loc.begin.is?('/')
14
+ error_message('') if slashes > max
15
+ else
16
+ error_message('only ') if slashes <= max
17
+ end
18
+ add_offence(:convention, node.loc.expression, msg) if msg
19
+
20
+ super
21
+ end
22
+
23
+ def self.max_slashes
24
+ RegexpLiteral.config['MaxSlashes']
25
+ end
26
+
27
+ private
28
+
29
+ def error_message(word)
30
+ sprintf('Use %%r %sfor regular expressions matching more ' +
31
+ "than %d '/' character%s.",
32
+ word,
33
+ RegexpLiteral.max_slashes,
34
+ RegexpLiteral.max_slashes == 1 ? '' : 's')
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,55 @@
1
+ # encoding: utf-8
2
+
3
+ module Rubocop
4
+ module Cop
5
+ module Style
6
+ # This cop checks for uses of rescue in its modifier form.
7
+ class RescueModifier < Cop
8
+ MSG = 'Avoid using rescue in its modifier form.'
9
+
10
+ def on_kwbegin(node)
11
+ body, *_ = *node
12
+ return if normal_rescue?(body)
13
+ super
14
+ end
15
+
16
+ def on_def(node)
17
+ _method_name, _args, body = *node
18
+ return if normal_rescue?(body)
19
+ super
20
+ end
21
+
22
+ def on_defs(node)
23
+ _receiver, _method_name, _args, body = *node
24
+ return if normal_rescue?(body)
25
+ super
26
+ end
27
+
28
+ def normal_rescue?(node)
29
+ return false unless node
30
+
31
+ case node.type
32
+ when :rescue
33
+ # Skip only the rescue node and continue processing its children.
34
+ process_regular_node(node)
35
+ true
36
+ when :ensure
37
+ first_child = node.children.first
38
+ if first_child && first_child.type == :rescue
39
+ process_regular_node(first_child)
40
+ true
41
+ else
42
+ false
43
+ end
44
+ else
45
+ false
46
+ end
47
+ end
48
+
49
+ def on_rescue(node)
50
+ add_offence(:convention, node.loc.expression, MSG)
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,51 @@
1
+ # encoding: utf-8
2
+
3
+ module Rubocop
4
+ module Cop
5
+ module Style
6
+ # This cop checks for multiple expressions placed on the same line.
7
+ # It also checks for lines terminated with a semicolon.
8
+ class Semicolon < Cop
9
+ MSG = 'Do not use semicolons to terminate expressions.'
10
+
11
+ def inspect(source_buffer, source, tokens, ast, comments)
12
+ return unless ast
13
+
14
+ on_node(:begin, ast) do |node|
15
+ exprs = node.children
16
+
17
+ next if exprs.size < 2
18
+
19
+ # create a map matching lines to the number of expressions on them
20
+ exprs_lines = exprs.map { |e| e.loc.expression.line }
21
+ lines = exprs_lines.group_by { |i| i }
22
+
23
+ # every line with more than 1 expression on it is an offence
24
+ lines.each do |line, expr_on_line|
25
+ if expr_on_line.size > 1
26
+ # TODO: Find the correct position of the semicolon. We don't
27
+ # know if the first semicolon on the line is a separator of
28
+ # expressions. It's just a guess.
29
+ column = source[line - 1].index(';')
30
+ add_offence(:convention,
31
+ source_range(source_buffer, source[0...(line - 1)],
32
+ column, 1),
33
+ MSG)
34
+ end
35
+ end
36
+ end
37
+
38
+ tokens.group_by { |t| t.pos.line }.each do |line, line_tokens|
39
+ if line_tokens.last.type == :tSEMI # rubocop:disable SymbolName
40
+ column = line_tokens.last.pos.column
41
+ add_offence(:convention,
42
+ source_range(source_buffer, source[0...(line - 1)],
43
+ column, 1),
44
+ MSG)
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,48 @@
1
+ # encoding: utf-8
2
+
3
+ module Rubocop
4
+ module Cop
5
+ module Style
6
+ # This cop checks for single-line method definitions.
7
+ # It can optionally accept single-line methods with no body.
8
+ class SingleLineMethods < Cop
9
+ MSG = 'Avoid single-line method definitions.'
10
+
11
+ def allow_empty?
12
+ SingleLineMethods.config['AllowIfMethodIsEmpty']
13
+ end
14
+
15
+ def on_def(node)
16
+ check(node)
17
+
18
+ super
19
+ end
20
+
21
+ def on_defs(node)
22
+ check(node)
23
+
24
+ super
25
+ end
26
+
27
+ private
28
+
29
+ def check(node)
30
+ start_line = node.loc.keyword.line
31
+ end_line = node.loc.end.line
32
+
33
+ if node.type == :def
34
+ empty_body = node.children[2].nil?
35
+ else
36
+ empty_body = node.children[3].nil?
37
+ end
38
+
39
+ if start_line == end_line && !(allow_empty? && empty_body)
40
+ add_offence(:convention,
41
+ node.loc.expression,
42
+ MSG)
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,69 @@
1
+ # encoding: utf-8
2
+
3
+ # rubocop:disable SymbolName
4
+
5
+ module Rubocop
6
+ module Cop
7
+ module Style
8
+ # Common functionality for cops checking for missing space after
9
+ # punctuation.
10
+ module SpaceAfterCommaEtc
11
+ MSG = 'Space missing after %s.'
12
+
13
+ def inspect(source_buffer, source, tokens, ast, comments)
14
+ tokens.each_cons(2) do |t1, t2|
15
+ if kind(t1) && t1.pos.line == t2.pos.line &&
16
+ t2.pos.column == t1.pos.column + offset(t1)
17
+ add_offence(:convention, t1.pos, sprintf(MSG, kind(t1)))
18
+ end
19
+ end
20
+ end
21
+
22
+ # The normal offset, i.e., the distance from the punctuation
23
+ # token where a space should be, is 1.
24
+ def offset(token)
25
+ 1
26
+ end
27
+ end
28
+
29
+ # Checks for comma (,) not follwed by some kind of space.
30
+ class SpaceAfterComma < Cop
31
+ include SpaceAfterCommaEtc
32
+
33
+ def kind(token)
34
+ 'comma' if token.type == :tCOMMA
35
+ end
36
+ end
37
+
38
+ # Checks for semicolon (;) not follwed by some kind of space.
39
+ class SpaceAfterSemicolon < Cop
40
+ include SpaceAfterCommaEtc
41
+
42
+ def kind(token)
43
+ 'semicolon' if token.type == :tSEMI
44
+ end
45
+ end
46
+
47
+ # Checks for colon (:) not follwed by some kind of space.
48
+ class SpaceAfterColon < Cop
49
+ include SpaceAfterCommaEtc
50
+
51
+ # The colon following a label will not appear in the token
52
+ # array. Instad we get a tLABEL token, whose length we use to
53
+ # calculate where we expect a space.
54
+ def offset(token)
55
+ case token.type
56
+ when :tLABEL then token.text.length + 1
57
+ when :tCOLON then 1
58
+ end
59
+ end
60
+
61
+ def kind(token)
62
+ case token.type
63
+ when :tLABEL, :tCOLON then 'colon'
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,32 @@
1
+ # encoding: utf-8
2
+
3
+ module Rubocop
4
+ module Cop
5
+ module Style
6
+ # Checks for various control keywords missing a space after them.
7
+ class SpaceAfterControlKeyword < Cop
8
+ MSG = 'Use space after control keywords.'
9
+ # elsif and unless are handled by on_if.
10
+ KEYWORDS = %w(if case when while until)
11
+
12
+ def on_keyword(node)
13
+ return if node.loc.is_a?(Parser::Source::Map::Ternary)
14
+
15
+ exp = node.loc.expression
16
+ kw = node.loc.keyword
17
+ kw_offset = kw.begin_pos - exp.begin_pos
18
+ if exp.source[kw_offset..-1].start_with?(kw.source + '(')
19
+ add_offence(:convention, kw, MSG)
20
+ end
21
+ end
22
+
23
+ KEYWORDS.each do |keyword|
24
+ define_method(:"on_#{keyword}") do |node|
25
+ on_keyword(node)
26
+ super(node)
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,36 @@
1
+ # encoding: utf-8
2
+
3
+ module Rubocop
4
+ module Cop
5
+ module Style
6
+ # Checks for uses of double quotes where single quotes would do.
7
+ class StringLiterals < Cop
8
+ MSG = "Prefer single-quoted strings when you don't need " +
9
+ 'string interpolation or special symbols.'
10
+
11
+ def on_str(node)
12
+ # Constants like __FILE__ are handled as strings,
13
+ # but don't respond to begin.
14
+ return unless node.loc.respond_to?(:begin)
15
+
16
+ # regex matches IF there is a ' or there is a \\ in the string that
17
+ # is not preceeded/followed by another \\ (e.g. "\\x34") but not
18
+ # "\\\\"
19
+ if node.loc.expression.source !~ /('|([^\\]|\A)\\([^\\]|\Z))/ &&
20
+ node.loc.begin.is?('"')
21
+ add_offence(:convention, node.loc.expression, MSG)
22
+ do_autocorrect(node)
23
+ end
24
+ end
25
+
26
+ alias_method :on_dstr, :ignore_node
27
+ alias_method :on_regexp, :ignore_node
28
+
29
+ def autocorrect_action(node)
30
+ replace(node.loc.begin, "'")
31
+ replace(node.loc.end, "'")
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,314 @@
1
+ # encoding: utf-8
2
+
3
+ # rubocop:disable SymbolName
4
+
5
+ module Rubocop
6
+ module Cop
7
+ module Style
8
+ # Common functionality for checking surrounding space.
9
+ module SurroundingSpace
10
+ def space_between?(t1, t2)
11
+ char_preceding_2nd_token =
12
+ @source[t2.pos.line - 1][t2.pos.column - 1]
13
+ if char_preceding_2nd_token == '+' && t1.type != :tPLUS
14
+ # Special case. A unary plus is not present in the tokens.
15
+ char_preceding_2nd_token =
16
+ @source[t2.pos.line - 1][t2.pos.column - 2]
17
+ end
18
+ t2.pos.line > t1.pos.line || char_preceding_2nd_token == ' '
19
+ end
20
+
21
+ def index_of_first_token(node, tokens)
22
+ @token_table ||= build_token_table(tokens)
23
+ b = node.loc.expression.begin
24
+ @token_table[[b.line, b.column]]
25
+ end
26
+
27
+ def index_of_last_token(node, tokens)
28
+ @token_table ||= build_token_table(tokens)
29
+ e = node.loc.expression.end
30
+ (0...e.column).to_a.reverse.find do |c|
31
+ ix = @token_table[[e.line, c]]
32
+ return ix if ix
33
+ end
34
+ end
35
+
36
+ def build_token_table(tokens)
37
+ table = {}
38
+ tokens.each_with_index do |t, ix|
39
+ table[[t.pos.line, t.pos.column]] = ix
40
+ end
41
+ table
42
+ end
43
+ end
44
+
45
+ # Checks that operators have space around them, except for **
46
+ # which should not have surrounding space.
47
+ class SpaceAroundOperators < Cop
48
+ include SurroundingSpace
49
+ MSG_MISSING = "Surrounding space missing for operator '%s'."
50
+ MSG_DETECTED = 'Space around operator ** detected.'
51
+
52
+ BINARY_OPERATORS =
53
+ [:tEQL, :tAMPER2, :tPIPE, :tCARET, :tPLUS, :tMINUS, :tSTAR2,
54
+ :tDIVIDE, :tPERCENT, :tEH, :tCOLON, :tANDOP, :tOROP, :tMATCH,
55
+ :tNMATCH, :tEQ, :tNEQ, :tGT, :tRSHFT, :tGEQ, :tLT,
56
+ :tLSHFT, :tLEQ, :tASSOC, :tEQQ, :tCMP, :tOP_ASGN]
57
+
58
+ def inspect(source_buffer, source, tokens, sexp, comments)
59
+ return unless sexp
60
+
61
+ @source = source
62
+ positions_not_to_check = get_positions_not_to_check(tokens, sexp)
63
+
64
+ tokens.each_cons(3) do |token_before, token, token_after|
65
+ next if token_before.type == :kDEF # TODO: remove?
66
+ next if token_before.type == :tDOT # Called as method.
67
+ next if positions_not_to_check.include?(token.pos)
68
+
69
+ case token.type
70
+ when :tPOW
71
+ if has_space?(token_before, token, token_after)
72
+ add_offence(:convention, token.pos, MSG_DETECTED)
73
+ end
74
+ when *BINARY_OPERATORS
75
+ check_missing_space(token_before, token, token_after)
76
+ end
77
+ end
78
+ end
79
+
80
+ # Returns an array of positions marking the tokens that this cop
81
+ # should not check, either because the token is not an operator
82
+ # or because another cop does the check.
83
+ def get_positions_not_to_check(tokens, sexp)
84
+ positions_not_to_check = []
85
+ do_not_check_block_arg_pipes(sexp, positions_not_to_check)
86
+ do_not_check_param_default(tokens, sexp, positions_not_to_check)
87
+ do_not_check_class_lshift_self(tokens, sexp, positions_not_to_check)
88
+ do_not_check_def_things(tokens, sexp, positions_not_to_check)
89
+ do_not_check_singleton_operator_defs(tokens, sexp,
90
+ positions_not_to_check)
91
+ positions_not_to_check
92
+ end
93
+
94
+ def do_not_check_block_arg_pipes(sexp, positions_not_to_check)
95
+ # each { |a| }
96
+ # ^ ^
97
+ on_node(:block, sexp) do |b|
98
+ on_node(:args, b) do |a|
99
+ positions_not_to_check << a.loc.begin << a.loc.end if a.loc.begin
100
+ end
101
+ end
102
+ end
103
+
104
+ def do_not_check_param_default(tokens, sexp, positions_not_to_check)
105
+ # func(a, b=nil)
106
+ # ^
107
+ on_node(:optarg, sexp) do |optarg|
108
+ _arg, equals, _value = tokens[index_of_first_token(optarg, tokens),
109
+ 3]
110
+ positions_not_to_check << equals.pos
111
+ end
112
+ end
113
+
114
+ def do_not_check_class_lshift_self(tokens,
115
+ sexp,
116
+ positions_not_to_check)
117
+ # class <<self
118
+ # ^
119
+ on_node(:sclass, sexp) do |sclass|
120
+ ix = index_of_first_token(sclass, tokens)
121
+ if tokens[ix, 2].map(&:type) == [:kCLASS, :tLSHFT]
122
+ positions_not_to_check << tokens[ix + 1].pos
123
+ end
124
+ end
125
+ end
126
+
127
+ def do_not_check_def_things(tokens, sexp, positions_not_to_check)
128
+ # def +(other)
129
+ # ^
130
+ on_node(:def, sexp) do |def_node|
131
+ # def each &block
132
+ # ^
133
+ # def each *args
134
+ # ^
135
+ on_node([:blockarg, :restarg], def_node) do |arg_node|
136
+ positions_not_to_check <<
137
+ tokens[index_of_first_token(arg_node, tokens)].pos
138
+ end
139
+ positions_not_to_check <<
140
+ tokens[index_of_first_token(def_node, tokens) + 1].pos
141
+ end
142
+ end
143
+
144
+ def do_not_check_singleton_operator_defs(tokens, sexp,
145
+ positions_not_to_check)
146
+ # def self.===(other)
147
+ # ^
148
+ on_node(:defs, sexp) do |defs_node|
149
+ _receiver, name, _args = *defs_node
150
+ ix = index_of_first_token(defs_node, tokens)
151
+ name_token = tokens[ix..-1].find { |t| t.text == name.to_s }
152
+ positions_not_to_check << name_token.pos
153
+ end
154
+ end
155
+
156
+ def check_missing_space(token_before, token, token_after)
157
+ unless has_space?(token_before, token, token_after)
158
+ text = token.text.to_s + (token.type == :tOP_ASGN ? '=' : '')
159
+ add_offence(:convention, token.pos, MSG_MISSING % text)
160
+ end
161
+ end
162
+
163
+ def has_space?(token_before, token, token_after)
164
+ space_between?(token_before, token) && space_between?(token,
165
+ token_after)
166
+ end
167
+ end
168
+
169
+ # Checks that block braces have surrounding space.
170
+ class SpaceAroundBraces < Cop
171
+ include SurroundingSpace
172
+ MSG_LEFT = "Surrounding space missing for '{'."
173
+ MSG_RIGHT = "Space missing to the left of '}'."
174
+
175
+ def inspect(source_buffer, source, tokens, sexp, comments)
176
+ return unless sexp
177
+ @source = source
178
+ positions_not_to_check = get_positions_not_to_check(tokens, sexp)
179
+ tokens.each_cons(2) do |t1, t2|
180
+ next if ([t1.pos, t2.pos] - positions_not_to_check).size < 2
181
+
182
+ type1, type2 = t1.type, t2.type
183
+ # :tLBRACE in hash literals, :tLCURLY otherwise.
184
+ next if [:tLCURLY, :tLBRACE].include?(type1) && type2 == :tRCURLY
185
+ check(t1, t2, MSG_LEFT) if type1 == :tLCURLY || type2 == :tLCURLY
186
+ check(t1, t2, MSG_RIGHT) if type2 == :tRCURLY
187
+ end
188
+ end
189
+
190
+ def get_positions_not_to_check(tokens, sexp)
191
+ positions_not_to_check = []
192
+
193
+ on_node(:hash, sexp) do |hash|
194
+ b_ix = index_of_first_token(hash, tokens)
195
+ e_ix = index_of_last_token(hash, tokens)
196
+ positions_not_to_check << tokens[b_ix].pos << tokens[e_ix].pos
197
+ end
198
+
199
+ # TODO: Check braces inside string/symbol/regexp/xstr interpolation.
200
+ on_node([:dstr, :dsym, :regexp, :xstr], sexp) do |s|
201
+ b_ix = index_of_first_token(s, tokens)
202
+ e_ix = index_of_last_token(s, tokens)
203
+ tokens[b_ix..e_ix].each do |t|
204
+ positions_not_to_check << t.pos if t.type == :tRCURLY
205
+ end
206
+ end
207
+
208
+ positions_not_to_check
209
+ end
210
+
211
+ def check(t1, t2, msg)
212
+ unless space_between?(t1, t2)
213
+ brace_token = msg == MSG_LEFT ? t1 : t2
214
+ add_offence(:convention, brace_token.pos, msg)
215
+ end
216
+ end
217
+ end
218
+
219
+ # Common functionality for checking for spaces inside various
220
+ # kinds of parentheses.
221
+ module SpaceInside
222
+ include SurroundingSpace
223
+ MSG = 'Space inside %s detected.'
224
+
225
+ def inspect(source_buffer, source, tokens, sexp, comments)
226
+ @source = source
227
+ left, right, kind = specifics
228
+ tokens.each_cons(2) do |t1, t2|
229
+ if t1.type == left || t2.type == right
230
+ if t2.pos.line == t1.pos.line && space_between?(t1, t2)
231
+ space_range = Parser::Source::Range.new(source_buffer,
232
+ t1.pos.end_pos,
233
+ t2.pos.begin_pos)
234
+ add_offence(:convention, space_range, format(MSG, kind))
235
+ end
236
+ end
237
+ end
238
+ end
239
+ end
240
+
241
+ # Checks for spaces inside ordinary round parentheses.
242
+ class SpaceInsideParens < Cop
243
+ include SpaceInside
244
+
245
+ def specifics
246
+ [:tLPAREN2, :tRPAREN, 'parentheses']
247
+ end
248
+ end
249
+
250
+ # Checks for spaces inside square brackets.
251
+ class SpaceInsideBrackets < Cop
252
+ include SpaceInside
253
+
254
+ def specifics
255
+ [:tLBRACK, :tRBRACK, 'square brackets']
256
+ end
257
+ end
258
+
259
+ # Checks that braces used for hash literals have or don't have
260
+ # surrounding space depending on configuration.
261
+ class SpaceInsideHashLiteralBraces < Cop
262
+ include SurroundingSpace
263
+ MSG = 'Space inside hash literal braces %s.'
264
+
265
+ def inspect(source_buffer, source, tokens, sexp, comments)
266
+ return unless sexp
267
+ @source = source
268
+ on_node(:hash, sexp) do |hash|
269
+ b_ix = index_of_first_token(hash, tokens)
270
+ e_ix = index_of_last_token(hash, tokens)
271
+ if tokens[b_ix].type == :tLBRACE # Hash literal with braces?
272
+ check(tokens[b_ix], tokens[b_ix + 1])
273
+ check(tokens[e_ix - 1], tokens[e_ix])
274
+ end
275
+ end
276
+ end
277
+
278
+ def check(t1, t2)
279
+ types = [t1, t2].map(&:type)
280
+ braces = [:tLBRACE, :tRCURLY]
281
+ return if types == braces || (braces - types).size == 2
282
+ # No offence if line break inside.
283
+ return if t1.pos.line < t2.pos.line
284
+ has_space = space_between?(t1, t2)
285
+ is_offence, word = if self.class.config['EnforcedStyleIsWithSpaces']
286
+ [!has_space, 'missing']
287
+ else
288
+ [has_space, 'detected']
289
+ end
290
+ add_offence(:convention, t1.pos, sprintf(MSG, word)) if is_offence
291
+ end
292
+ end
293
+
294
+ # Checks that the equals signs in parameter default assignments
295
+ # have surrounding space.
296
+ class SpaceAroundEqualsInParameterDefault < Cop
297
+ include SurroundingSpace
298
+ MSG = 'Surrounding space missing in default value assignment.'
299
+
300
+ def inspect(source_buffer, source, tokens, sexp, comments)
301
+ return unless sexp
302
+ @source = source
303
+ on_node(:optarg, sexp) do |optarg|
304
+ index = index_of_first_token(optarg, tokens)
305
+ arg, equals, value = tokens[index, 3]
306
+ unless space_between?(arg, equals) && space_between?(equals, value)
307
+ add_offence(:convention, equals.pos, MSG)
308
+ end
309
+ end
310
+ end
311
+ end
312
+ end
313
+ end
314
+ end