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
@@ -0,0 +1,31 @@
1
+ # encoding: utf-8
2
+
3
+ module Rubocop
4
+ module Cop
5
+ # Handles adding and checking ignored nodes.
6
+ module IgnoredNode
7
+ def ignore_node(node)
8
+ @ignored_nodes ||= []
9
+ @ignored_nodes << node
10
+ end
11
+
12
+ def part_of_ignored_node?(node)
13
+ return false unless @ignored_nodes
14
+ expression = node.loc.expression
15
+ @ignored_nodes.each do |ignored_node|
16
+ if ignored_node.loc.expression.begin_pos <= expression.begin_pos &&
17
+ ignored_node.loc.expression.end_pos >= expression.end_pos
18
+ return true
19
+ end
20
+ end
21
+
22
+ false
23
+ end
24
+
25
+ def ignored_node?(node)
26
+ # Same object found in array?
27
+ @ignored_nodes && @ignored_nodes.any? { |n| n.eql?(node) }
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,50 @@
1
+ # encoding: utf-8
2
+
3
+ module Rubocop
4
+ module Cop
5
+ module Lint
6
+ # This cop checks for ambiguous operators in the first argument of a
7
+ # method invocation without parentheses.
8
+ #
9
+ # @example
10
+ # array = [1, 2, 3]
11
+ #
12
+ # # The `*` is interpreted as a splat operator but it could possibly be
13
+ # # a `*` method invocation (i.e. `do_something.*(array)`).
14
+ # do_something *array
15
+ #
16
+ # # With parentheses, there's no ambiguity.
17
+ # do_something(*array)
18
+ class AmbiguousOperator < Cop
19
+ include ParserDiagnostic
20
+
21
+ AMBIGUITIES = {
22
+ '+' => { actual: 'positive number', possible: 'addition' },
23
+ '-' => { actual: 'negative number', possible: 'subtraction' },
24
+ '*' => { actual: 'splat', possible: 'multiplication' },
25
+ '&' => { actual: 'block', possible: 'binary AND' },
26
+ '**' => { actual: 'keyword splat', possible: 'exponent' }
27
+ }.each do |key, hash|
28
+ hash[:operator] = key
29
+ end
30
+
31
+ MSG_FORMAT = 'Ambiguous %{actual} operator. Parenthesize the method ' +
32
+ "arguments if it's surely a %{actual} operator, or add " +
33
+ 'a whitespace to the right of the %{operator} if it ' +
34
+ 'should be a %{possible}.'
35
+
36
+ private
37
+
38
+ def relevant_diagnostic?(diagnostic)
39
+ diagnostic.reason == :ambiguous_prefix
40
+ end
41
+
42
+ def alternative_message(diagnostic)
43
+ operator = diagnostic.location.source
44
+ hash = AMBIGUITIES[operator]
45
+ format(MSG_FORMAT, hash)
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,36 @@
1
+ # encoding: utf-8
2
+
3
+ module Rubocop
4
+ module Cop
5
+ module Lint
6
+ # This cop checks for ambiguous regexp literals in the first argument of
7
+ # a method invocation without parentheses.
8
+ #
9
+ # @example
10
+ # # This is interpreted as a method invocation with a regexp literal,
11
+ # # but it could possibly be `/` method invocations.
12
+ # # (i.e. `do_something./(pattern)./(i)`)
13
+ # do_something /pattern/i
14
+ #
15
+ # # With parentheses, there's no ambiguity.
16
+ # do_something(/pattern/i)
17
+ class AmbiguousRegexpLiteral < Cop
18
+ include ParserDiagnostic
19
+
20
+ MSG = 'Ambiguous regexp literal. Parenthesize the method arguments ' +
21
+ "if it's surely a regexp literal, or add a whitespace to the " +
22
+ 'right of the / if it should be a division.'
23
+
24
+ private
25
+
26
+ def relevant_diagnostic?(diagnostic)
27
+ diagnostic.reason == :ambiguous_literal
28
+ end
29
+
30
+ def alternative_message(diagnostic)
31
+ MSG
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -6,7 +6,8 @@ module Rubocop
6
6
  # This cop checks for assignments in the conditions of
7
7
  # if/while/until.
8
8
  class AssignmentInCondition < Cop
9
- ASGN_NODES = [:lvasgn, :ivasgn, :cvasgn, :gvasgn, :casgn]
9
+ include SafeAssignment
10
+
10
11
  MSG = 'Assignment in condition - you probably meant to use ==.'
11
12
 
12
13
  def on_if(node)
@@ -29,7 +30,7 @@ module Rubocop
29
30
  # assignments inside blocks are not what we're looking for
30
31
  return if condition.type == :block
31
32
 
32
- on_node([:begin, *ASGN_NODES], condition) do |asgn_node|
33
+ on_node([:begin, *EQUALS_ASGN_NODES], condition) do |asgn_node|
33
34
  # skip safe assignment nodes if safe assignment is allowed
34
35
  return if safe_assignment_allowed? && safe_assignment?(asgn_node)
35
36
 
@@ -39,15 +40,6 @@ module Rubocop
39
40
  end
40
41
  end
41
42
  end
42
-
43
- def safe_assignment?(node)
44
- node.type == :begin && node.children.size == 1 &&
45
- ASGN_NODES.include?(node.children[0].type)
46
- end
47
-
48
- def safe_assignment_allowed?
49
- cop_config['AllowSafeAssignment']
50
- end
51
43
  end
52
44
  end
53
45
  end
@@ -12,6 +12,8 @@ module Rubocop
12
12
  # i
13
13
  # end
14
14
  class BlockAlignment < Cop
15
+ include CheckAssignment
16
+
15
17
  MSG = 'end at %d, %d is not aligned with %s at %d, %d%s'
16
18
 
17
19
  def initialize(config = nil, options = nil)
@@ -36,40 +38,24 @@ module Rubocop
36
38
 
37
39
  alias_method :on_or, :on_and
38
40
 
39
- def on_lvasgn(node)
40
- _, children = *node
41
- process_block_assignment(node, children)
42
- end
43
-
44
- alias_method :on_ivasgn, :on_lvasgn
45
- alias_method :on_cvasgn, :on_lvasgn
46
- alias_method :on_gvasgn, :on_lvasgn
47
- alias_method :on_and_asgn, :on_lvasgn
48
- alias_method :on_or_asgn, :on_lvasgn
49
-
50
- def on_casgn(node)
51
- _, _, children = *node
52
- process_block_assignment(node, children)
53
- end
54
-
55
41
  def on_op_asgn(node)
56
42
  variable, _op, args = *node
57
- process_block_assignment(variable, args)
43
+ check_assignment(variable, args)
58
44
  end
59
45
 
60
46
  def on_send(node)
61
47
  _receiver, _method, *args = *node
62
- process_block_assignment(node, args.last)
48
+ check_assignment(node, args.last)
63
49
  end
64
50
 
65
51
  def on_masgn(node)
66
52
  variables, args = *node
67
- process_block_assignment(variables, args)
53
+ check_assignment(variables, args)
68
54
  end
69
55
 
70
56
  private
71
57
 
72
- def process_block_assignment(begin_node, other_node)
58
+ def check_assignment(begin_node, other_node)
73
59
  return unless other_node
74
60
 
75
61
  block_node = find_block_node(other_node)
@@ -0,0 +1,52 @@
1
+ # encoding: utf-8
2
+
3
+ module Rubocop
4
+ module Cop
5
+ module Lint
6
+ # This cop checks for conditions that are not on the same line as
7
+ # if/while/until.
8
+ #
9
+ # @example
10
+ #
11
+ # if
12
+ # some_condition
13
+ # do_something
14
+ # end
15
+ class ConditionPosition < Cop
16
+ def on_if(node)
17
+ return if node.loc.respond_to?(:question)
18
+
19
+ check(node)
20
+ end
21
+
22
+ def on_while(node)
23
+ check(node)
24
+ end
25
+
26
+ def on_until(node)
27
+ check(node)
28
+ end
29
+
30
+ private
31
+
32
+ def check(node)
33
+ condition, = *node
34
+
35
+ if on_different_line?(node.loc.keyword.line,
36
+ condition.loc.expression.line)
37
+ add_offence(condition, :expression,
38
+ message(node.loc.keyword.source))
39
+ end
40
+ end
41
+
42
+ def message(keyword)
43
+ "Place the condition on the same line as #{keyword}."
44
+ end
45
+
46
+ def on_different_line?(keyword_line, cond_line)
47
+ keyword_line != cond_line
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,57 @@
1
+ # encoding: utf-8
2
+
3
+ module Rubocop
4
+ module Cop
5
+ module Lint
6
+ # This cop checks for odd else block layout - like
7
+ # having an expression on the same line as the else keyword,
8
+ # which is usually a mistake.
9
+ #
10
+ # @example
11
+ #
12
+ # if something
13
+ # ...
14
+ # else do_this
15
+ # do_that
16
+ # end
17
+ class ElseLayout < Cop
18
+ def on_if(node)
19
+ # ignore ternary ops
20
+ return if node.loc.respond_to?(:question)
21
+ # ignore modifier ops & elsif nodes
22
+ return unless node.loc.end
23
+
24
+ check(node)
25
+ end
26
+
27
+ private
28
+
29
+ def check(node)
30
+ return unless node
31
+
32
+ if node.loc.respond_to?(:else) &&
33
+ node.loc.else &&
34
+ node.loc.else.is?('else')
35
+ _cond, _if_branch, else_branch = *node
36
+
37
+ return unless else_branch && else_branch.type == :begin
38
+
39
+ first_else_expr = else_branch.children.first
40
+
41
+ if first_else_expr.loc.expression.line == node.loc.else.line
42
+ add_offence(first_else_expr, :expression, message)
43
+ end
44
+ elsif node.loc.respond_to?(:keyword) &&
45
+ %w(if elsif).include?(node.loc.keyword.source)
46
+ _cond, _if_branch, else_branch = *node
47
+ check(else_branch)
48
+ end
49
+ end
50
+
51
+ def message
52
+ 'Odd else layout detected. Perhaps you meant to use elsif instead?'
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -18,6 +18,7 @@ module Rubocop
18
18
  class EndAlignment < Cop
19
19
  include CheckMethods
20
20
  include CheckAssignment
21
+ include ConfigurableEnforcedStyle
21
22
 
22
23
  MSG = 'end at %d, %d is not aligned with %s at %d, %d'
23
24
 
@@ -41,8 +42,32 @@ module Rubocop
41
42
  check(node)
42
43
  end
43
44
 
45
+ def on_send(node)
46
+ receiver, method_name, *args = *node
47
+ if visibility_and_def_on_same_line?(receiver, method_name, args)
48
+ expr = node.loc.expression
49
+ method_def = args.first
50
+ range = Parser::Source::Range.new(expr.source_buffer,
51
+ expr.begin_pos,
52
+ method_def.loc.keyword.end_pos)
53
+ check_offset(method_def, range.source,
54
+ method_def.loc.keyword.begin_pos - expr.begin_pos)
55
+ ignore_node(method_def) # Don't check the same `end` again.
56
+ end
57
+ end
58
+
44
59
  private
45
60
 
61
+ # Returns true for constructs such as
62
+ # private def my_method
63
+ # which are allowed in Ruby 2.1 and later.
64
+ def visibility_and_def_on_same_line?(receiver, method_name, args)
65
+ !receiver &&
66
+ [:public, :protected, :private,
67
+ :module_function].include?(method_name) &&
68
+ args.size == 1 && [:def, :defs].include?(args.first.type)
69
+ end
70
+
46
71
  def check_assignment(node, rhs)
47
72
  # If there are method calls chained to the right hand side of the
48
73
  # assignment, we let rhs be the receiver of those method calls before
@@ -55,7 +80,7 @@ module Rubocop
55
80
  when :if, :while, :until
56
81
  return if rhs.loc.respond_to?(:question) # ternary
57
82
 
58
- offset = if alignment == :variable
83
+ offset = if style == :variable
59
84
  rhs.loc.keyword.column - node.loc.expression.column
60
85
  else
61
86
  0
@@ -85,16 +110,16 @@ module Rubocop
85
110
  kw_loc.column != end_loc.column + offset
86
111
  add_offence(nil, end_loc,
87
112
  sprintf(MSG, end_loc.line, end_loc.column,
88
- alignment_base, kw_loc.line, kw_loc.column))
113
+ alignment_base, kw_loc.line, kw_loc.column)) do
114
+ opposite_style_detected
115
+ end
116
+ else
117
+ correct_style_detected
89
118
  end
90
119
  end
91
120
 
92
- def alignment
93
- a = cop_config['AlignWith']
94
- case a
95
- when 'keyword', 'variable' then a.to_sym
96
- else fail "Unknown AlignWith: #{a}"
97
- end
121
+ def parameter_name
122
+ 'AlignWith'
98
123
  end
99
124
  end
100
125
  end
@@ -0,0 +1,37 @@
1
+ # encoding: utf-8
2
+
3
+ module Rubocop
4
+ module Cop
5
+ module Lint
6
+ # This cop checks for invalid character literals with a non-escaped
7
+ # whitespace character (e.g. `? `).
8
+ # However, currently it's unclear whether there's a way to emit this
9
+ # warning without syntax errors.
10
+ #
11
+ # $ ruby -w
12
+ # p(? )
13
+ # -:1: warning: invalid character syntax; use ?\s
14
+ # -:1: syntax error, unexpected '?', expecting ')'
15
+ # p(? )
16
+ # ^
17
+ #
18
+ # @example
19
+ # p(? )
20
+ class InvalidCharacterLiteral < Cop
21
+ include ParserDiagnostic
22
+
23
+ private
24
+
25
+ def relevant_diagnostic?(diagnostic)
26
+ diagnostic.reason == :invalid_escape_use
27
+ end
28
+
29
+ def alternative_message(diagnostic)
30
+ diagnostic.message
31
+ .capitalize
32
+ .gsub('character syntax', 'character literal')
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -14,10 +14,8 @@ module Rubocop
14
14
 
15
15
  def on_send(node)
16
16
  _receiver, method_name, args = *node
17
- if OPERATOR_METHODS.include?(method_name) ||
18
- method_name.to_s.end_with?('=')
19
- return
20
- end
17
+ return if operator?(method_name) || method_name.to_s.end_with?('=')
18
+
21
19
  if args && args.loc.expression.source.start_with?('(')
22
20
  space_length = spaces_before_left_parenthesis(node)
23
21
  if space_length > 0
@@ -3,11 +3,11 @@
3
3
  module Rubocop
4
4
  module Cop
5
5
  module Lint
6
- # This cop actually inspects nothing, just repacks Parser's diagnostics
7
- # into RuboCop's offences.
8
- # The purpose of this cop is to support disabling Syntax offences with
9
- # config or inline comments by conforming to the cop framework.
10
- class Syntax < Cop
6
+ # This is actually not a cop and inspects nothing. It just provides
7
+ # methods to repack Parser's diagnostics into RuboCop's offences.
8
+ module Syntax
9
+ COP_NAME = 'Syntax'.freeze
10
+
11
11
  def self.offences_from_diagnostics(diagnostics)
12
12
  diagnostics.map do |diagnostic|
13
13
  offence_from_diagnostic(diagnostic)
@@ -19,15 +19,9 @@ module Rubocop
19
19
  diagnostic.level,
20
20
  diagnostic.location,
21
21
  diagnostic.message,
22
- cop_name
22
+ COP_NAME
23
23
  )
24
24
  end
25
-
26
- def investigate(processed_source)
27
- processed_source.diagnostics.each do |d|
28
- add_offence(nil, d.location, d.message, d.level)
29
- end
30
- end
31
25
  end
32
26
  end
33
27
  end