rubocop 0.16.0 → 0.17.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 (189) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +3 -1
  4. data/CHANGELOG.md +44 -0
  5. data/CONTRIBUTING.md +40 -8
  6. data/Gemfile +6 -0
  7. data/README.md +65 -20
  8. data/Rakefile +0 -1
  9. data/config/default.yml +15 -3
  10. data/config/enabled.yml +143 -109
  11. data/lib/rubocop.rb +45 -26
  12. data/lib/rubocop/cli.rb +26 -27
  13. data/lib/rubocop/config.rb +0 -1
  14. data/lib/rubocop/config_loader.rb +16 -23
  15. data/lib/rubocop/cop/commissioner.rb +2 -7
  16. data/lib/rubocop/cop/cop.rb +24 -51
  17. data/lib/rubocop/cop/ignored_node.rb +31 -0
  18. data/lib/rubocop/cop/lint/ambiguous_operator.rb +50 -0
  19. data/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb +36 -0
  20. data/lib/rubocop/cop/lint/assignment_in_condition.rb +3 -11
  21. data/lib/rubocop/cop/lint/block_alignment.rb +6 -20
  22. data/lib/rubocop/cop/lint/condition_position.rb +52 -0
  23. data/lib/rubocop/cop/lint/else_layout.rb +57 -0
  24. data/lib/rubocop/cop/lint/end_alignment.rb +33 -8
  25. data/lib/rubocop/cop/lint/invalid_character_literal.rb +37 -0
  26. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +2 -4
  27. data/lib/rubocop/cop/lint/syntax.rb +6 -12
  28. data/lib/rubocop/cop/lint/useless_else_without_rescue.rb +25 -0
  29. data/lib/rubocop/cop/mixin/array_syntax.rb +20 -0
  30. data/lib/rubocop/cop/mixin/autocorrect_alignment.rb +76 -0
  31. data/lib/rubocop/cop/mixin/check_assignment.rb +26 -0
  32. data/lib/rubocop/cop/{check_methods.rb → mixin/check_methods.rb} +0 -0
  33. data/lib/rubocop/cop/mixin/code_length.rb +33 -0
  34. data/lib/rubocop/cop/mixin/configurable_enforced_style.rb +53 -0
  35. data/lib/rubocop/cop/mixin/configurable_max.rb +19 -0
  36. data/lib/rubocop/cop/mixin/configurable_naming.rb +45 -0
  37. data/lib/rubocop/cop/{style → mixin}/if_node.rb +0 -0
  38. data/lib/rubocop/cop/mixin/if_then_else.rb +23 -0
  39. data/lib/rubocop/cop/mixin/negative_conditional.rb +24 -0
  40. data/lib/rubocop/cop/mixin/parser_diagnostic.rb +34 -0
  41. data/lib/rubocop/cop/mixin/safe_assignment.rb +19 -0
  42. data/lib/rubocop/cop/mixin/space_after_punctuation.rb +32 -0
  43. data/lib/rubocop/cop/mixin/space_inside.rb +31 -0
  44. data/lib/rubocop/cop/mixin/statement_modifier.rb +59 -0
  45. data/lib/rubocop/cop/mixin/string_help.rb +32 -0
  46. data/lib/rubocop/cop/mixin/surrounding_space.rb +42 -0
  47. data/lib/rubocop/cop/rails/default_scope.rb +3 -1
  48. data/lib/rubocop/cop/style/accessor_method_name.rb +4 -12
  49. data/lib/rubocop/cop/style/braces_around_hash_parameters.rb +16 -1
  50. data/lib/rubocop/cop/style/case_indentation.rb +33 -16
  51. data/lib/rubocop/cop/style/character_literal.rb +10 -0
  52. data/lib/rubocop/cop/style/dot_position.rb +23 -6
  53. data/lib/rubocop/cop/style/empty_lines_around_body.rb +5 -5
  54. data/lib/rubocop/cop/style/favor_unless_over_negated_if.rb +1 -32
  55. data/lib/rubocop/cop/style/favor_until_over_negated_while.rb +20 -0
  56. data/lib/rubocop/cop/style/hash_syntax.rb +5 -1
  57. data/lib/rubocop/cop/style/if_unless_modifier.rb +34 -0
  58. data/lib/rubocop/cop/style/if_with_semicolon.rb +1 -1
  59. data/lib/rubocop/cop/style/indentation_consistency.rb +51 -0
  60. data/lib/rubocop/cop/style/indentation_width.rb +0 -26
  61. data/lib/rubocop/cop/style/lambda_call.rb +12 -5
  62. data/lib/rubocop/cop/style/method_def_parentheses.rb +29 -11
  63. data/lib/rubocop/cop/style/multiline_if_then.rb +4 -9
  64. data/lib/rubocop/cop/style/multiline_ternary_operator.rb +22 -0
  65. data/lib/rubocop/cop/style/{ternary_operator.rb → nested_ternary_operator.rb} +0 -15
  66. data/lib/rubocop/cop/style/numeric_literals.rb +30 -2
  67. data/lib/rubocop/cop/style/one_line_conditional.rb +2 -1
  68. data/lib/rubocop/cop/style/parameter_lists.rb +7 -3
  69. data/lib/rubocop/cop/style/parentheses_around_condition.rb +9 -11
  70. data/lib/rubocop/cop/style/predicate_name.rb +4 -12
  71. data/lib/rubocop/cop/style/raise_args.rb +19 -11
  72. data/lib/rubocop/cop/style/regexp_literal.rb +19 -6
  73. data/lib/rubocop/cop/style/space_after_colon.rb +36 -0
  74. data/lib/rubocop/cop/style/space_after_comma.rb +16 -0
  75. data/lib/rubocop/cop/style/space_after_semicolon.rb +16 -0
  76. data/lib/rubocop/cop/style/space_around_block_braces.rb +38 -38
  77. data/lib/rubocop/cop/style/space_around_operators.rb +1 -2
  78. data/lib/rubocop/cop/style/space_inside_hash_literal_braces.rb +6 -2
  79. data/lib/rubocop/cop/style/string_literals.rb +5 -5
  80. data/lib/rubocop/cop/style/trailing_comma.rb +94 -0
  81. data/lib/rubocop/cop/style/unless_else.rb +2 -2
  82. data/lib/rubocop/cop/style/while_until_modifier.rb +32 -0
  83. data/lib/rubocop/cop/style/word_array.rb +9 -1
  84. data/lib/rubocop/cop/util.rb +14 -0
  85. data/lib/rubocop/cop/variable_inspector.rb +11 -6
  86. data/lib/rubocop/cop/variable_inspector/scope.rb +4 -3
  87. data/lib/rubocop/file_inspector.rb +22 -6
  88. data/lib/rubocop/formatter/clang_style_formatter.rb +1 -1
  89. data/lib/rubocop/formatter/colorizable.rb +37 -0
  90. data/lib/rubocop/formatter/disabled_config_formatter.rb +27 -6
  91. data/lib/rubocop/formatter/progress_formatter.rb +1 -1
  92. data/lib/rubocop/formatter/simple_text_formatter.rb +9 -5
  93. data/lib/rubocop/options.rb +19 -4
  94. data/lib/rubocop/target_finder.rb +4 -0
  95. data/lib/rubocop/version.rb +1 -1
  96. data/rubocop-todo.yml +10 -2
  97. data/rubocop.gemspec +3 -2
  98. data/spec/project_spec.rb +12 -7
  99. data/spec/rubocop/cli_spec.rb +262 -99
  100. data/spec/rubocop/config_loader_spec.rb +5 -5
  101. data/spec/rubocop/config_spec.rb +3 -3
  102. data/spec/rubocop/config_store_spec.rb +12 -11
  103. data/spec/rubocop/cop/commissioner_spec.rb +21 -5
  104. data/spec/rubocop/cop/cop_spec.rb +1 -1
  105. data/spec/rubocop/cop/lint/ambiguous_operator_spec.rb +113 -0
  106. data/spec/rubocop/cop/lint/ambiguous_regexp_literal_spec.rb +35 -0
  107. data/spec/rubocop/cop/lint/block_alignment_spec.rb +2 -2
  108. data/spec/rubocop/cop/lint/condition_position_spec.rb +49 -0
  109. data/spec/rubocop/cop/lint/else_layout_spec.rb +65 -0
  110. data/spec/rubocop/cop/lint/end_alignment_spec.rb +41 -1
  111. data/spec/rubocop/cop/lint/invalid_character_literal_spec.rb +33 -0
  112. data/spec/rubocop/cop/lint/parentheses_as_grouped_expression_spec.rb +3 -3
  113. data/spec/rubocop/cop/lint/shadowing_outer_local_variable_spec.rb +12 -12
  114. data/spec/rubocop/cop/lint/syntax_spec.rb +2 -2
  115. data/spec/rubocop/cop/lint/useless_assignment_spec.rb +72 -54
  116. data/spec/rubocop/cop/lint/useless_else_without_rescue_spec.rb +48 -0
  117. data/spec/rubocop/cop/offence_spec.rb +1 -1
  118. data/spec/rubocop/cop/rails/default_scope_spec.rb +6 -0
  119. data/spec/rubocop/cop/rails/output_spec.rb +2 -1
  120. data/spec/rubocop/cop/style/align_hash_spec.rb +9 -9
  121. data/spec/rubocop/cop/style/align_parameters_spec.rb +1 -1
  122. data/spec/rubocop/cop/style/braces_around_hash_parameters_spec.rb +5 -0
  123. data/spec/rubocop/cop/style/case_indentation_spec.rb +53 -2
  124. data/spec/rubocop/cop/style/class_and_module_camel_case_spec.rb +3 -3
  125. data/spec/rubocop/cop/style/documentation_spec.rb +0 -1
  126. data/spec/rubocop/cop/style/dot_position_spec.rb +18 -3
  127. data/spec/rubocop/cop/style/empty_line_between_defs_spec.rb +4 -4
  128. data/spec/rubocop/cop/style/empty_lines_around_body_spec.rb +13 -0
  129. data/spec/rubocop/cop/style/favor_unless_over_negated_if_spec.rb +1 -1
  130. data/spec/rubocop/cop/style/favor_until_over_negated_while_spec.rb +1 -1
  131. data/spec/rubocop/cop/style/hash_syntax_spec.rb +5 -0
  132. data/spec/rubocop/cop/style/{favor_modifier_spec.rb → if_unless_modifier_spec.rb} +4 -111
  133. data/spec/rubocop/cop/style/indentation_consistency_spec.rb +490 -0
  134. data/spec/rubocop/cop/style/indentation_width_spec.rb +19 -91
  135. data/spec/rubocop/cop/style/lambda_call_spec.rb +18 -0
  136. data/spec/rubocop/cop/style/method_called_on_do_end_block_spec.rb +2 -2
  137. data/spec/rubocop/cop/style/method_def_parentheses_spec.rb +35 -1
  138. data/spec/rubocop/cop/style/method_length_spec.rb +1 -0
  139. data/spec/rubocop/cop/style/method_name_spec.rb +27 -5
  140. data/spec/rubocop/cop/style/multiline_block_chain_spec.rb +4 -4
  141. data/spec/rubocop/cop/style/multiline_if_then_spec.rb +2 -2
  142. data/spec/rubocop/cop/style/multiline_ternary_operator_spec.rb +18 -0
  143. data/spec/rubocop/cop/style/{ternary_operator_spec.rb → nested_ternary_operator_spec.rb} +0 -15
  144. data/spec/rubocop/cop/style/numeric_literals_spec.rb +18 -1
  145. data/spec/rubocop/cop/style/one_line_conditional_spec.rb +2 -1
  146. data/spec/rubocop/cop/style/parameter_lists_spec.rb +1 -0
  147. data/spec/rubocop/cop/style/parentheses_around_condition_spec.rb +13 -4
  148. data/spec/rubocop/cop/style/raise_args_spec.rb +22 -0
  149. data/spec/rubocop/cop/style/redundant_self_spec.rb +4 -4
  150. data/spec/rubocop/cop/style/regexp_literal_spec.rb +4 -0
  151. data/spec/rubocop/cop/style/space_after_colon_spec.rb +12 -4
  152. data/spec/rubocop/cop/style/space_after_method_name_spec.rb +2 -2
  153. data/spec/rubocop/cop/style/space_around_block_braces_spec.rb +30 -1
  154. data/spec/rubocop/cop/style/{space_around_equals_in_default_parameter_spec.rb → space_around_equals_in_parameter_default_spec.rb} +0 -0
  155. data/spec/rubocop/cop/style/space_around_operators_spec.rb +2 -1
  156. data/spec/rubocop/cop/style/space_inside_hash_literal_braces_spec.rb +20 -3
  157. data/spec/rubocop/cop/style/string_literals_spec.rb +33 -0
  158. data/spec/rubocop/cop/style/trailing_comma_spec.rb +200 -0
  159. data/spec/rubocop/cop/style/variable_name_spec.rb +27 -3
  160. data/spec/rubocop/cop/style/while_until_modifier_spec.rb +75 -0
  161. data/spec/rubocop/cop/style/word_array_spec.rb +1 -0
  162. data/spec/rubocop/cop/team_spec.rb +1 -1
  163. data/spec/rubocop/cop/variable_inspector/scope_spec.rb +3 -4
  164. data/spec/rubocop/file_inspector_spec.rb +1 -1
  165. data/spec/rubocop/formatter/base_formatter_spec.rb +12 -11
  166. data/spec/rubocop/formatter/colorizable_spec.rb +107 -0
  167. data/spec/rubocop/formatter/disabled_config_formatter_spec.rb +2 -0
  168. data/spec/rubocop/formatter/formatter_set_spec.rb +1 -1
  169. data/spec/rubocop/formatter/json_formatter_spec.rb +4 -3
  170. data/spec/rubocop/formatter/progress_formatter_spec.rb +2 -2
  171. data/spec/rubocop/options_spec.rb +3 -1
  172. data/spec/rubocop/target_finder_spec.rb +13 -11
  173. data/spec/spec_helper.rb +5 -1
  174. data/spec/support/shared_examples.rb +2 -2
  175. data/spec/support/statement_modifier_helper.rb +41 -0
  176. metadata +88 -30
  177. data/lib/rubocop/cop/check_assignment.rb +0 -43
  178. data/lib/rubocop/cop/style/array_syntax.rb +0 -22
  179. data/lib/rubocop/cop/style/autocorrect_alignment.rb +0 -78
  180. data/lib/rubocop/cop/style/code_length.rb +0 -35
  181. data/lib/rubocop/cop/style/configurable_enforced_style.rb +0 -51
  182. data/lib/rubocop/cop/style/configurable_max.rb +0 -17
  183. data/lib/rubocop/cop/style/configurable_naming.rb +0 -41
  184. data/lib/rubocop/cop/style/favor_modifier.rb +0 -118
  185. data/lib/rubocop/cop/style/if_then_else.rb +0 -27
  186. data/lib/rubocop/cop/style/space_after_comma_etc.rb +0 -73
  187. data/lib/rubocop/cop/style/space_inside.rb +0 -33
  188. data/lib/rubocop/cop/style/string_help.rb +0 -30
  189. data/lib/rubocop/cop/style/surrounding_space.rb +0 -44
@@ -18,23 +18,15 @@ module Rubocop
18
18
  # # good
19
19
  # def value? ...
20
20
  class PredicateName < Cop
21
- def on_def(node)
22
- method_name, args, _body = *node
23
- check(node, method_name.to_s, args)
24
- end
25
-
26
- def on_defs(node)
27
- _scope, method_name, args, _body = *node
28
- check(node, method_name.to_s, args)
29
- end
21
+ include CheckMethods
30
22
 
31
23
  private
32
24
 
33
- def check(node, method_name, args)
25
+ def check(node, method_name, args, _body)
34
26
  prefix_blacklist.each do |prefix|
35
- if method_name.start_with?(prefix)
27
+ if method_name.to_s.start_with?(prefix)
36
28
  add_offence(node, :name,
37
- message(method_name, prefix))
29
+ message(method_name.to_s, prefix))
38
30
  end
39
31
  end
40
32
  end
@@ -23,25 +23,33 @@ module Rubocop
23
23
  def check_compact(node)
24
24
  _receiver, selector, *args = *node
25
25
 
26
- return unless args.size > 1
27
-
28
- add_offence(node, :expression, message(selector))
26
+ if args.size > 1
27
+ add_offence(node, :expression, message(selector)) do
28
+ opposite_style_detected
29
+ end
30
+ else
31
+ correct_style_detected
32
+ end
29
33
  end
30
34
 
31
35
  def check_exploded(node)
32
36
  _receiver, selector, *args = *node
33
37
 
34
- return unless args.size == 1
35
-
36
- arg, = *args
38
+ if args.size == 1
39
+ arg, = *args
37
40
 
38
- if arg.type == :send && arg.loc.selector.is?('new')
39
- _receiver, _selector, *constructor_args = *arg
41
+ if arg.type == :send && arg.loc.selector.is?('new')
42
+ _receiver, _selector, *constructor_args = *arg
40
43
 
41
- # Allow code like `raise Ex.new(arg1, arg2)`.
42
- unless constructor_args.size > 1
43
- add_offence(node, :expression, message(selector))
44
+ # Allow code like `raise Ex.new(arg1, arg2)`.
45
+ if constructor_args.size <= 1
46
+ add_offence(node, :expression, message(selector)) do
47
+ opposite_style_detected
48
+ end
49
+ end
44
50
  end
51
+ else
52
+ correct_style_detected
45
53
  end
46
54
  end
47
55
 
@@ -7,16 +7,25 @@ module Rubocop
7
7
  # on how many escaped slashes there are in the regexp and on the
8
8
  # value of the configuration parameter MaxSlashes.
9
9
  class RegexpLiteral < Cop
10
+ include ConfigurableMax
11
+
10
12
  def on_regexp(node)
11
13
  string_parts = node.children.select { |child| child.type == :str }
12
14
  total_string = string_parts.map { |s| s.loc.expression.source }.join
13
15
  slashes = total_string.count('/')
14
- msg = if node.loc.begin.is?('/')
15
- error_message('') if slashes > max_slashes
16
- else
17
- error_message('only ') if slashes <= max_slashes
18
- end
19
- add_offence(node, :expression, msg) if msg
16
+ if node.loc.begin.is?('/')
17
+ if slashes > max_slashes
18
+ msg = error_message('')
19
+ safe_setting = slashes
20
+ end
21
+ elsif slashes <= max_slashes
22
+ msg = error_message('only ')
23
+ safe_setting = slashes + 1
24
+ end
25
+
26
+ if msg
27
+ add_offence(node, :expression, msg) { self.max = safe_setting }
28
+ end
20
29
  end
21
30
 
22
31
  def max_slashes
@@ -25,6 +34,10 @@ module Rubocop
25
34
 
26
35
  private
27
36
 
37
+ def parameter_name
38
+ 'MaxSlashes'
39
+ end
40
+
28
41
  def error_message(word)
29
42
  sprintf('Use %%r %sfor regular expressions matching more ' +
30
43
  "than %d '/' character%s.",
@@ -0,0 +1,36 @@
1
+ # encoding: utf-8
2
+
3
+ module Rubocop
4
+ module Cop
5
+ module Style
6
+ # Checks for colon (:) not follwed by some kind of space.
7
+ class SpaceAfterColon < Cop
8
+ include IfNode
9
+
10
+ MSG = 'Space missing after colon.'
11
+
12
+ def on_pair(node)
13
+ oper = node.loc.operator
14
+ if oper.is?(':') && oper.source_buffer.source[oper.end_pos] =~ /\S/
15
+ add_offence(oper, oper)
16
+ end
17
+ end
18
+
19
+ def on_if(node)
20
+ if ternary_op?(node)
21
+ colon = node.loc.colon
22
+ if colon.source_buffer.source[colon.end_pos] =~ /\S/
23
+ add_offence(colon, colon)
24
+ end
25
+ end
26
+ end
27
+
28
+ def autocorrect(range)
29
+ @corrections << lambda do |corrector|
30
+ corrector.insert_after(range, ' ')
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,16 @@
1
+ # encoding: utf-8
2
+
3
+ module Rubocop
4
+ module Cop
5
+ module Style
6
+ # Checks for comma (,) not follwed by some kind of space.
7
+ class SpaceAfterComma < Cop
8
+ include SpaceAfterPunctuation
9
+
10
+ def kind(token)
11
+ 'comma' if token.type == :tCOMMA
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ # encoding: utf-8
2
+
3
+ module Rubocop
4
+ module Cop
5
+ module Style
6
+ # Checks for semicolon (;) not follwed by some kind of space.
7
+ class SpaceAfterSemicolon < Cop
8
+ include SpaceAfterPunctuation
9
+
10
+ def kind(token)
11
+ 'semicolon' if token.type == :tSEMI
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -42,28 +42,29 @@ module Rubocop
42
42
  sb = node.loc.expression.source_buffer
43
43
 
44
44
  if left_brace.end_pos == right_brace.begin_pos
45
- no_space(style_for_empty_braces, sb, left_brace.begin_pos,
46
- right_brace.end_pos, 'Space missing inside empty braces.')
45
+ if style_for_empty_braces == :space
46
+ offence(sb, left_brace.begin_pos, right_brace.end_pos,
47
+ 'Space missing inside empty braces.')
48
+ end
47
49
  else
48
50
  range = Parser::Source::Range.new(sb, left_brace.end_pos,
49
51
  right_brace.begin_pos)
50
52
  inner = range.source
51
53
  unless inner =~ /\n/
52
54
  if inner =~ /\S/
53
- braces_with_contents_inside(node, inner)
54
- else
55
- space(style_for_empty_braces, sb, range.begin_pos,
56
- range.end_pos, 'Space inside empty braces detected.')
55
+ braces_with_contents_inside(node, inner, sb)
56
+ elsif style_for_empty_braces == :no_space
57
+ offence(sb, range.begin_pos, range.end_pos,
58
+ 'Space inside empty braces detected.')
57
59
  end
58
60
  end
59
61
  end
60
62
  end
61
63
 
62
- def braces_with_contents_inside(node, inner)
64
+ def braces_with_contents_inside(node, inner, sb)
63
65
  _method, args, _body = *node
64
66
  left_brace, right_brace = node.loc.begin, node.loc.end
65
67
  pipe = args.loc.begin
66
- sb = node.loc.expression.source_buffer
67
68
 
68
69
  if inner =~ /^\S/
69
70
  no_space_inside_left_brace(left_brace, pipe, sb)
@@ -72,8 +73,8 @@ module Rubocop
72
73
  end
73
74
 
74
75
  if inner =~ /\S$/
75
- no_space(style_for_inside_braces, sb, right_brace.begin_pos,
76
- right_brace.end_pos, 'Space missing inside }.')
76
+ no_space(sb, right_brace.begin_pos, right_brace.end_pos,
77
+ 'Space missing inside }.')
77
78
  else
78
79
  space_inside_right_brace(right_brace, sb)
79
80
  end
@@ -81,55 +82,58 @@ module Rubocop
81
82
 
82
83
  def no_space_inside_left_brace(left_brace, pipe, sb)
83
84
  if pipe
84
- if left_brace.end_pos == pipe.begin_pos
85
- no_space(style_for_block_parameters, sb, left_brace.begin_pos,
86
- pipe.end_pos, 'Space between { and | missing.')
85
+ if left_brace.end_pos == pipe.begin_pos &&
86
+ cop_config['SpaceBeforeBlockParameters']
87
+ offence(sb, left_brace.begin_pos, pipe.end_pos,
88
+ 'Space between { and | missing.')
87
89
  end
88
90
  else
89
91
  # We indicate the position after the left brace. Otherwise it's
90
92
  # difficult to distinguish between space missing to the left and to
91
93
  # the right of the brace in autocorrect.
92
- no_space(style_for_inside_braces, sb, left_brace.end_pos,
93
- left_brace.end_pos + 1, 'Space missing inside {.')
94
+ no_space(sb, left_brace.end_pos, left_brace.end_pos + 1,
95
+ 'Space missing inside {.')
94
96
  end
95
97
  end
96
98
 
97
99
  def space_inside_left_brace(left_brace, pipe, sb)
98
100
  if pipe
99
- space(style_for_block_parameters, sb, left_brace.end_pos,
100
- pipe.begin_pos, 'Space between { and | detected.')
101
+ unless cop_config['SpaceBeforeBlockParameters']
102
+ offence(sb, left_brace.end_pos, pipe.begin_pos,
103
+ 'Space between { and | detected.')
104
+ end
101
105
  else
102
106
  brace_with_space = range_with_surrounding_space(left_brace, :right)
103
- space(style_for_inside_braces, sb, brace_with_space.begin_pos + 1,
104
- brace_with_space.end_pos, 'Space inside { detected.')
107
+ space(sb, brace_with_space.begin_pos + 1, brace_with_space.end_pos,
108
+ 'Space inside { detected.')
105
109
  end
106
110
  end
107
111
 
108
112
  def space_inside_right_brace(right_brace, sb)
109
113
  brace_with_space = range_with_surrounding_space(right_brace, :left)
110
- space(style_for_inside_braces, sb, brace_with_space.begin_pos,
111
- brace_with_space.end_pos - 1, 'Space inside } detected.')
114
+ space(sb, brace_with_space.begin_pos, brace_with_space.end_pos - 1,
115
+ 'Space inside } detected.')
112
116
  end
113
117
 
114
- def no_space(specific_style, sb, begin_pos, end_pos, msg)
115
- offence(sb, begin_pos, end_pos, msg) if specific_style == :space
118
+ def no_space(sb, begin_pos, end_pos, msg)
119
+ if style == :space_inside_braces
120
+ offence(sb, begin_pos, end_pos, msg) { opposite_style_detected }
121
+ else
122
+ correct_style_detected
123
+ end
116
124
  end
117
125
 
118
- def space(specific_style, sb, begin_pos, end_pos, msg)
119
- offence(sb, begin_pos, end_pos, msg) if specific_style == :no_space
126
+ def space(sb, begin_pos, end_pos, msg)
127
+ if style == :no_space_inside_braces
128
+ offence(sb, begin_pos, end_pos, msg) { opposite_style_detected }
129
+ else
130
+ correct_style_detected
131
+ end
120
132
  end
121
133
 
122
134
  def offence(sb, begin_pos, end_pos, msg)
123
135
  range = Parser::Source::Range.new(sb, begin_pos, end_pos)
124
- add_offence(range, range, msg)
125
- end
126
-
127
- def available_styles
128
- %w(space_inside_braces no_space_inside_braces)
129
- end
130
-
131
- def style_for_inside_braces
132
- style == :space_inside_braces ? :space : :no_space
136
+ add_offence(range, range, msg) { yield if block_given? }
133
137
  end
134
138
 
135
139
  def style_for_empty_braces
@@ -140,10 +144,6 @@ module Rubocop
140
144
  end
141
145
  end
142
146
 
143
- def style_for_block_parameters
144
- cop_config['SpaceBeforeBlockParameters'] ? :space : :no_space
145
- end
146
-
147
147
  def autocorrect(range)
148
148
  @corrections << lambda do |corrector|
149
149
  case range.source
@@ -6,8 +6,7 @@ module Rubocop
6
6
  # Checks that operators have space around them, except for **
7
7
  # which should not have surrounding space.
8
8
  class SpaceAroundOperators < Cop
9
- TYPES = %w(and or class
10
- op_asgn and_asgn or_asgn masgn casgn lvasgn ivasgn gvasgn)
9
+ TYPES = %w(and or class) + ASGN_NODES
11
10
 
12
11
  TYPES.each { |t| define_method(:"on_#{t}") { |node| check(node) } }
13
12
 
@@ -40,8 +40,12 @@ module Rubocop
40
40
  if offence?(t1, t2, expect_space)
41
41
  brace = (t1.text == '{' ? t1 : t2).pos
42
42
  range = expect_space ? brace : space_range(brace)
43
- add_offence(range, range,
44
- message(brace, is_empty_braces, expect_space))
43
+ add_offence(range, range, message(brace, is_empty_braces,
44
+ expect_space)) do
45
+ opposite_style_detected
46
+ end
47
+ else
48
+ correct_style_detected
45
49
  end
46
50
  end
47
51
 
@@ -12,17 +12,17 @@ module Rubocop
12
12
 
13
13
  def message(node)
14
14
  if style == :single_quotes
15
- "Prefer single-quoted strings when you don't need string " +
16
- 'interpolation or special symbols.'
15
+ "Prefer single-quoted strings when you don't need string " \
16
+ 'interpolation or special symbols.'
17
17
  else
18
- 'Prefer double-quoted strings unless you need single quotes to ' +
19
- 'avoid extra backslashes for escaping.'
18
+ 'Prefer double-quoted strings unless you need single quotes to ' \
19
+ 'avoid extra backslashes for escaping.'
20
20
  end
21
21
  end
22
22
 
23
23
  def offence?(node)
24
24
  src = node.loc.expression.source
25
- return false if src =~ /^(%q|\?|<<-)/i
25
+ return false if src =~ /^(%[qQ]?|\?|<<-)/i
26
26
  src !~ if style == :single_quotes
27
27
  # regex matches IF there is a ' or there is a \\ in the
28
28
  # string that is not preceeded/followed by another \\
@@ -0,0 +1,94 @@
1
+ # encoding: utf-8
2
+
3
+ module Rubocop
4
+ module Cop
5
+ module Style
6
+ # This cop checks for trailing comma in parameter lists and literals.
7
+ class TrailingComma < Cop
8
+ include ConfigurableEnforcedStyle
9
+
10
+ MSG = '%s comma after the last %s.'
11
+
12
+ def on_array(node)
13
+ check_literal(node, 'item of %s array')
14
+ end
15
+
16
+ def on_hash(node)
17
+ check_literal(node, 'item of %s hash')
18
+ end
19
+
20
+ def on_send(node)
21
+ _receiver, _method_name, *args = *node
22
+ return if args.empty?
23
+ # It's impossible for a method call without parentheses to have
24
+ # a trailing comma.
25
+ return unless brackets?(node)
26
+
27
+ check(node, args, 'parameter of %s method call',
28
+ args.last.loc.expression.end_pos, node.loc.expression.end_pos)
29
+ end
30
+
31
+ private
32
+
33
+ def parameter_name
34
+ 'EnforcedStyleForMultiline'
35
+ end
36
+
37
+ def check_literal(node, kind)
38
+ return if node.children.empty?
39
+ # A braceless hash is the last parameter of a method call and will be
40
+ # checked as such.
41
+ return unless brackets?(node)
42
+
43
+ check(node, node.children, kind,
44
+ node.children.last.loc.expression.end_pos,
45
+ node.loc.end.begin_pos)
46
+ end
47
+
48
+ def check(node, items, kind, begin_pos, end_pos)
49
+ sb = items.first.loc.expression.source_buffer
50
+ after_last_item = Parser::Source::Range.new(sb, begin_pos, end_pos)
51
+ comma_offset = after_last_item.source =~ /,/
52
+ should_have_comma = style == :comma && multiline?(node)
53
+ if comma_offset
54
+ unless should_have_comma
55
+ avoid_comma(items, kind,
56
+ after_last_item.begin_pos + comma_offset, sb)
57
+ end
58
+ elsif should_have_comma
59
+ put_comma(items, kind, sb)
60
+ end
61
+ end
62
+
63
+ # Returns true if the node has round/square/curly brackets.
64
+ def brackets?(node)
65
+ !node.loc.end.nil?
66
+ end
67
+
68
+ # Returns true if the round/square/curly brackets of the given node are
69
+ # on different lines.
70
+ def multiline?(node)
71
+ [node.loc.begin, node.loc.end].map(&:line).uniq.size > 1
72
+ end
73
+
74
+ def avoid_comma(items, kind, comma_begin_pos, sb)
75
+ range = Parser::Source::Range.new(sb, comma_begin_pos,
76
+ comma_begin_pos + 1)
77
+ article = kind =~ /array/ ? 'an' : 'a'
78
+ add_offence(nil, range,
79
+ sprintf(MSG, 'Avoid', sprintf(kind, article)))
80
+ end
81
+
82
+ def put_comma(items, kind, sb)
83
+ last_expr = items.last.loc.expression
84
+ ix = last_expr.source.rindex("\n") || 0
85
+ ix += last_expr.source[ix..-1] =~ /\S/
86
+ range = Parser::Source::Range.new(sb, last_expr.begin_pos + ix,
87
+ last_expr.end_pos)
88
+ add_offence(nil, range,
89
+ sprintf(MSG, 'Put a', sprintf(kind, 'a multiline')))
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end