rubocop 0.26.1 → 0.27.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 (155) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +5 -0
  3. data/.rubocop_todo.yml +10 -6
  4. data/.travis.yml +2 -0
  5. data/CHANGELOG.md +30 -0
  6. data/README.md +9 -2
  7. data/assets/logo.png +0 -0
  8. data/assets/output.html.erb +68 -65
  9. data/config/default.yml +42 -7
  10. data/config/disabled.yml +5 -0
  11. data/config/enabled.yml +32 -7
  12. data/lib/rubocop.rb +10 -2
  13. data/lib/rubocop/comment_config.rb +11 -17
  14. data/lib/rubocop/config.rb +20 -16
  15. data/lib/rubocop/config_loader.rb +8 -12
  16. data/lib/rubocop/cop/cop.rb +13 -12
  17. data/lib/rubocop/cop/lint/block_alignment.rb +4 -6
  18. data/lib/rubocop/cop/lint/def_end_alignment.rb +2 -2
  19. data/lib/rubocop/cop/lint/require_parentheses.rb +1 -1
  20. data/lib/rubocop/cop/lint/useless_access_modifier.rb +2 -3
  21. data/lib/rubocop/cop/lint/useless_setter_call.rb +2 -2
  22. data/lib/rubocop/cop/metrics/abc_size.rb +27 -0
  23. data/lib/rubocop/cop/metrics/block_nesting.rb +2 -4
  24. data/lib/rubocop/cop/metrics/class_length.rb +1 -1
  25. data/lib/rubocop/cop/metrics/line_length.rb +2 -5
  26. data/lib/rubocop/cop/metrics/method_length.rb +2 -2
  27. data/lib/rubocop/cop/mixin/autocorrect_alignment.rb +24 -15
  28. data/lib/rubocop/cop/mixin/autocorrect_unless_changing_ast.rb +15 -2
  29. data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +63 -0
  30. data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +1 -1
  31. data/lib/rubocop/cop/mixin/if_node.rb +3 -1
  32. data/lib/rubocop/cop/mixin/method_complexity.rb +3 -3
  33. data/lib/rubocop/cop/mixin/{on_method.rb → on_method_def.rb} +3 -3
  34. data/lib/rubocop/cop/mixin/space_after_punctuation.rb +2 -2
  35. data/lib/rubocop/cop/mixin/space_before_punctuation.rb +1 -1
  36. data/lib/rubocop/cop/mixin/statement_modifier.rb +2 -2
  37. data/lib/rubocop/cop/mixin/string_literals_help.rb +28 -0
  38. data/lib/rubocop/cop/rails/delegate.rb +2 -2
  39. data/lib/rubocop/cop/style/access_modifier_indentation.rb +2 -2
  40. data/lib/rubocop/cop/style/accessor_method_name.rb +2 -2
  41. data/lib/rubocop/cop/style/align_hash.rb +16 -12
  42. data/lib/rubocop/cop/style/align_parameters.rb +1 -1
  43. data/lib/rubocop/cop/style/and_or.rb +14 -6
  44. data/lib/rubocop/cop/style/array_join.rb +1 -1
  45. data/lib/rubocop/cop/style/block_comments.rb +16 -8
  46. data/lib/rubocop/cop/style/braces_around_hash_parameters.rb +6 -30
  47. data/lib/rubocop/cop/style/case_indentation.rb +20 -12
  48. data/lib/rubocop/cop/style/collection_methods.rb +4 -4
  49. data/lib/rubocop/cop/style/colon_method_call.rb +9 -0
  50. data/lib/rubocop/cop/style/comment_annotation.rb +1 -1
  51. data/lib/rubocop/cop/style/comment_indentation.rb +22 -22
  52. data/lib/rubocop/cop/style/def_with_parentheses.rb +2 -2
  53. data/lib/rubocop/cop/style/deprecated_hash_methods.rb +1 -1
  54. data/lib/rubocop/cop/style/double_negation.rb +6 -1
  55. data/lib/rubocop/cop/style/else_alignment.rb +93 -0
  56. data/lib/rubocop/cop/style/empty_line_between_defs.rb +1 -1
  57. data/lib/rubocop/cop/style/empty_lines.rb +1 -1
  58. data/lib/rubocop/cop/style/empty_lines_around_class_body.rb +34 -0
  59. data/lib/rubocop/cop/style/empty_lines_around_method_body.rb +37 -0
  60. data/lib/rubocop/cop/style/empty_lines_around_module_body.rb +30 -0
  61. data/lib/rubocop/cop/style/encoding.rb +1 -1
  62. data/lib/rubocop/cop/style/format_string.rb +4 -4
  63. data/lib/rubocop/cop/style/indent_array.rb +2 -2
  64. data/lib/rubocop/cop/style/indent_hash.rb +17 -12
  65. data/lib/rubocop/cop/style/indentation_width.rb +27 -19
  66. data/lib/rubocop/cop/style/method_call_parentheses.rb +3 -3
  67. data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +1 -1
  68. data/lib/rubocop/cop/style/method_def_parentheses.rb +17 -11
  69. data/lib/rubocop/cop/style/method_name.rb +1 -1
  70. data/lib/rubocop/cop/style/multiline_operation_indentation.rb +174 -0
  71. data/lib/rubocop/cop/style/non_nil_check.rb +12 -15
  72. data/lib/rubocop/cop/style/not.rb +1 -1
  73. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +12 -17
  74. data/lib/rubocop/cop/style/percent_q_literals.rb +1 -1
  75. data/lib/rubocop/cop/style/predicate_name.rb +2 -2
  76. data/lib/rubocop/cop/style/redundant_begin.rb +2 -2
  77. data/lib/rubocop/cop/style/redundant_return.rb +3 -3
  78. data/lib/rubocop/cop/style/redundant_self.rb +3 -3
  79. data/lib/rubocop/cop/style/regexp_literal.rb +17 -13
  80. data/lib/rubocop/cop/style/rescue_modifier.rb +2 -2
  81. data/lib/rubocop/cop/style/single_line_methods.rb +7 -4
  82. data/lib/rubocop/cop/style/space_after_method_name.rb +2 -2
  83. data/lib/rubocop/cop/style/space_around_equals_in_parameter_default.rb +17 -11
  84. data/lib/rubocop/cop/style/space_before_block_braces.rb +1 -1
  85. data/lib/rubocop/cop/style/space_inside_block_braces.rb +17 -14
  86. data/lib/rubocop/cop/style/space_inside_hash_literal_braces.rb +10 -6
  87. data/lib/rubocop/cop/style/string_literals.rb +13 -16
  88. data/lib/rubocop/cop/style/string_literals_in_interpolation.rb +41 -0
  89. data/lib/rubocop/cop/style/trailing_comma.rb +1 -3
  90. data/lib/rubocop/cop/style/trivial_accessors.rb +3 -3
  91. data/lib/rubocop/cop/style/unneeded_capital_w.rb +1 -1
  92. data/lib/rubocop/cop/style/unneeded_percent_q.rb +2 -2
  93. data/lib/rubocop/cop/style/word_array.rb +23 -19
  94. data/lib/rubocop/cop/team.rb +13 -26
  95. data/lib/rubocop/cop/util.rb +5 -0
  96. data/lib/rubocop/cop/variable_force/locatable.rb +7 -13
  97. data/lib/rubocop/formatter/disabled_config_formatter.rb +1 -1
  98. data/lib/rubocop/formatter/formatter_set.rb +9 -1
  99. data/lib/rubocop/formatter/html_formatter.rb +83 -55
  100. data/lib/rubocop/formatter/simple_text_formatter.rb +2 -2
  101. data/lib/rubocop/formatter/text_util.rb +25 -0
  102. data/lib/rubocop/options.rb +14 -7
  103. data/lib/rubocop/path_util.rb +11 -7
  104. data/lib/rubocop/runner.rb +7 -2
  105. data/lib/rubocop/version.rb +1 -1
  106. data/relnotes/v0.27.0.md +77 -0
  107. data/rubocop.gemspec +1 -1
  108. data/spec/fixtures/html_formatter/expected.html +495 -0
  109. data/spec/fixtures/html_formatter/project/app/controllers/application_controller.rb +5 -0
  110. data/spec/fixtures/html_formatter/project/app/controllers/books_controller.rb +74 -0
  111. data/spec/fixtures/html_formatter/project/app/models/book.rb +5 -0
  112. data/spec/rubocop/cli_spec.rb +56 -13
  113. data/spec/rubocop/cop/lint/invalid_character_literal_spec.rb +1 -1
  114. data/spec/rubocop/cop/metrics/abc_size_spec.rb +99 -0
  115. data/spec/rubocop/cop/rails/action_filter_spec.rb +1 -0
  116. data/spec/rubocop/cop/style/access_modifier_indentation_spec.rb +23 -1
  117. data/spec/rubocop/cop/style/align_hash_spec.rb +13 -0
  118. data/spec/rubocop/cop/style/align_parameters_spec.rb +44 -33
  119. data/spec/rubocop/cop/style/blocks_spec.rb +8 -0
  120. data/spec/rubocop/cop/style/braces_around_hash_parameters_spec.rb +9 -9
  121. data/spec/rubocop/cop/style/case_indentation_spec.rb +3 -2
  122. data/spec/rubocop/cop/style/colon_method_call_spec.rb +5 -0
  123. data/spec/rubocop/cop/style/comment_indentation_spec.rb +6 -1
  124. data/spec/rubocop/cop/style/else_alignment_spec.rb +437 -0
  125. data/spec/rubocop/cop/style/empty_lines_around_class_body_spec.rb +75 -0
  126. data/spec/rubocop/cop/style/{empty_lines_around_body_spec.rb → empty_lines_around_method_body_spec.rb} +9 -50
  127. data/spec/rubocop/cop/style/empty_lines_around_module_body_spec.rb +79 -0
  128. data/spec/rubocop/cop/style/file_name_spec.rb +1 -1
  129. data/spec/rubocop/cop/style/format_string_spec.rb +12 -0
  130. data/spec/rubocop/cop/style/indent_array_spec.rb +6 -1
  131. data/spec/rubocop/cop/style/indent_hash_spec.rb +2 -1
  132. data/spec/rubocop/cop/style/indentation_width_spec.rb +765 -722
  133. data/spec/rubocop/cop/style/multiline_operation_indentation_spec.rb +414 -0
  134. data/spec/rubocop/cop/style/non_nil_check_spec.rb +86 -55
  135. data/spec/rubocop/cop/style/single_line_methods_spec.rb +5 -1
  136. data/spec/rubocop/cop/style/space_before_block_braces_spec.rb +2 -1
  137. data/spec/rubocop/cop/style/space_inside_block_braces_spec.rb +2 -1
  138. data/spec/rubocop/cop/style/string_literals_in_interpolation_spec.rb +63 -0
  139. data/spec/rubocop/cop/style/string_literals_spec.rb +2 -2
  140. data/spec/rubocop/cop/style/word_array_spec.rb +15 -1
  141. data/spec/rubocop/formatter/base_formatter_spec.rb +1 -1
  142. data/spec/rubocop/formatter/disabled_lines_formatter_spec.rb +0 -1
  143. data/spec/rubocop/formatter/formatter_set_spec.rb +9 -0
  144. data/spec/rubocop/formatter/html_formatter_spec.rb +25 -122
  145. data/spec/rubocop/formatter/offense_count_formatter_spec.rb +0 -1
  146. data/spec/rubocop/runner_spec.rb +1 -1
  147. data/spec/spec_helper.rb +12 -130
  148. data/spec/support/cop_helper.rb +72 -0
  149. data/spec/support/coverage.rb +15 -0
  150. data/spec/support/{offenses_matcher.rb → custom_matchers.rb} +28 -0
  151. data/spec/support/jruby_workaround.rb +15 -0
  152. data/spec/support/{isolated_environment.rb → shared_contexts.rb} +19 -0
  153. metadata +49 -14
  154. data/lib/rubocop/cop/style/empty_lines_around_body.rb +0 -75
  155. data/spec/support/shared_context.rb +0 -20
@@ -31,7 +31,7 @@ module RuboCop
31
31
  lineno = target_method_lineno(node)
32
32
  line = node.loc.expression.source_buffer.source_line(lineno)
33
33
  indentation_of_line = /\S.*/.match(line).begin(0)
34
- indentation_of_line + 2
34
+ indentation_of_line + configured_indentation_width
35
35
  else
36
36
  args.first.loc.column
37
37
  end
@@ -63,12 +63,9 @@ module RuboCop
63
63
  replacement = (node.type == :and ? '&&' : '||')
64
64
  lambda do |corrector|
65
65
  [expr1, expr2].each do |expr|
66
- next unless expr.type == :send
67
- _receiver, method_name, *args = *expr
68
- # don't clobber if we already have a starting paren
69
- next unless !expr.loc.begin || expr.loc.begin.source != '('
70
- # don't touch anything unless we are sure it is a method call.
71
- next unless args.last && method_name.to_s =~ /[a-z]/
66
+ _receiver, _method_name, *args = *expr
67
+ next unless correctable?(expr)
68
+
72
69
  sb = expr.loc.expression.source_buffer
73
70
  begin_paren = expr.loc.selector.end_pos
74
71
  end_paren = begin_paren + 1
@@ -79,6 +76,17 @@ module RuboCop
79
76
  corrector.replace(node.loc.operator, replacement)
80
77
  end
81
78
  end
79
+
80
+ def correctable?(expr)
81
+ return false unless expr.type == :send
82
+ _receiver, method_name, *args = *expr
83
+ # don't clobber if we already have a starting paren
84
+ return false unless !expr.loc.begin || expr.loc.begin.source != '('
85
+ # don't touch anything unless we are sure it is a method call.
86
+ return false unless args.last && method_name.to_s =~ /[a-z]/
87
+
88
+ true
89
+ end
82
90
  end
83
91
  end
84
92
  end
@@ -14,7 +14,7 @@ module RuboCop
14
14
  def on_send(node)
15
15
  receiver_node, method_name, *arg_nodes = *node
16
16
  return unless receiver_node && receiver_node.type == :array &&
17
- method_name == :* && arg_nodes[0].type == :str
17
+ method_name == :* && arg_nodes[0].type == :str
18
18
 
19
19
  add_offense(node, :selector)
20
20
  end
@@ -13,15 +13,11 @@ module RuboCop
13
13
  end
14
14
  end
15
15
 
16
+ private
17
+
16
18
  def autocorrect(comment)
17
- expr = comment.loc.expression
18
- eq_begin = expr.resize("=begin\n".length)
19
- eq_end = Parser::Source::Range.new(expr.source_buffer,
20
- expr.end_pos - "\n=end".length,
21
- expr.end_pos)
22
- contents = Parser::Source::Range.new(expr.source_buffer,
23
- eq_begin.end_pos,
24
- eq_end.begin_pos)
19
+ eq_begin, eq_end, contents = parts(comment)
20
+
25
21
  @corrections << lambda do |corrector|
26
22
  corrector.remove(eq_begin)
27
23
  unless contents.length == 0
@@ -34,6 +30,18 @@ module RuboCop
34
30
  corrector.remove(eq_end)
35
31
  end
36
32
  end
33
+
34
+ def parts(comment)
35
+ expr = comment.loc.expression
36
+ eq_begin = expr.resize("=begin\n".length)
37
+ eq_end = Parser::Source::Range.new(expr.source_buffer,
38
+ expr.end_pos - "\n=end".length,
39
+ expr.end_pos)
40
+ contents = Parser::Source::Range.new(expr.source_buffer,
41
+ eq_begin.end_pos,
42
+ eq_end.begin_pos)
43
+ [eq_begin, eq_end, contents]
44
+ end
37
45
  end
38
46
  end
39
47
  end
@@ -28,28 +28,24 @@ module RuboCop
28
28
  if !braces?(arg) || all_hashes?(args)
29
29
  correct_style_detected
30
30
  else
31
- add_offense(arg, :expression,
32
- 'Redundant curly braces around a hash parameter.') do
33
- opposite_style_detected
34
- end
31
+ offense(arg, 'Redundant curly braces around a hash parameter.')
35
32
  end
36
33
  elsif braces?(arg)
37
34
  correct_style_detected
38
35
  else
39
- add_offense(arg, :expression,
40
- 'Missing curly braces around a hash parameter.') do
41
- opposite_style_detected
42
- end
36
+ offense(arg, 'Missing curly braces around a hash parameter.')
43
37
  end
44
38
  end
45
39
 
40
+ def offense(arg, msg)
41
+ add_offense(arg, :expression, msg) { opposite_style_detected }
42
+ end
43
+
46
44
  def autocorrect(node)
47
45
  @corrections << lambda do |corrector|
48
46
  if style == :no_braces
49
47
  corrector.remove(node.loc.begin)
50
48
  corrector.remove(node.loc.end)
51
- remove_leading_whitespace(node, corrector)
52
- remove_trailing_comma_and_whitespace(node, corrector)
53
49
  elsif style == :braces
54
50
  corrector.insert_before(node.loc.expression, '{')
55
51
  corrector.insert_after(node.loc.expression, '}')
@@ -57,26 +53,6 @@ module RuboCop
57
53
  end
58
54
  end
59
55
 
60
- def remove_leading_whitespace(node, corrector)
61
- corrector.remove(
62
- Parser::Source::Range.new(
63
- node.loc.expression.source_buffer,
64
- node.loc.begin.end_pos,
65
- node.children.first.loc.expression.begin_pos
66
- )
67
- )
68
- end
69
-
70
- def remove_trailing_comma_and_whitespace(node, corrector)
71
- corrector.remove(
72
- Parser::Source::Range.new(
73
- node.loc.expression.source_buffer,
74
- node.children.last.loc.expression.end_pos,
75
- node.loc.end.begin_pos
76
- )
77
- )
78
- end
79
-
80
56
  def non_empty_hash?(arg)
81
57
  arg && arg.type == :hash && arg.children.any?
82
58
  end
@@ -27,25 +27,33 @@ module RuboCop
27
27
  def check_when(when_node, case_node, base, indent, base_column)
28
28
  pos = when_node.loc.keyword
29
29
  expected_column = base_column +
30
- (indent ? IndentationWidth::CORRECT_INDENTATION : 0)
30
+ (indent ? configured_indentation_width : 0)
31
31
  if pos.column == expected_column
32
32
  correct_style_detected
33
33
  else
34
- msg = 'Indent `when` ' + if indent
35
- "one step more than `#{base}`."
36
- else
37
- "as deep as `#{base}`."
38
- end
39
- add_offense(when_node, pos, msg) do
40
- if pos.column == base_column(case_node, alternative_style)
41
- opposite_style_detected
42
- else
43
- unrecognized_style_detected
44
- end
34
+ incorrect_style(when_node, case_node, base, pos, indent)
35
+ end
36
+ end
37
+
38
+ def incorrect_style(when_node, case_node, base, pos, indent)
39
+ msg = 'Indent `when` ' + if indent
40
+ "one step more than `#{base}`."
41
+ else
42
+ "as deep as `#{base}`."
43
+ end
44
+ add_offense(when_node, pos, msg) do
45
+ if pos.column == base_column(case_node, alternative_style)
46
+ opposite_style_detected
47
+ else
48
+ unrecognized_style_detected
45
49
  end
46
50
  end
47
51
  end
48
52
 
53
+ def configured_indentation_width
54
+ config.for_cop('IndentationWidth')['Width']
55
+ end
56
+
49
57
  def parameter_name
50
58
  'IndentWhenRelativeTo'
51
59
  end
@@ -3,12 +3,12 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Style
6
- # This cop checks for uses of unidiomatic method names
6
+ # This cop enforces the use of consistent method names
7
7
  # from the Enumerable module.
8
8
  #
9
- # The current definition of the check is flawed and should be
10
- # enhanced by check for by blocks & procs as arguments of the
11
- # methods.
9
+ # Unfortunately we cannot actually know if a method is from
10
+ # Enumerable or not (static analysis limitation), so this cop
11
+ # can yield some false positives.
12
12
  class CollectionMethods < Cop
13
13
  MSG = 'Prefer `%s` over `%s`.'
14
14
 
@@ -8,7 +8,16 @@ module RuboCop
8
8
  class ColonMethodCall < Cop
9
9
  MSG = 'Do not use `::` for method calls.'
10
10
 
11
+ JAVA_TYPES = [:byte, :boolean, :byte, :short, :char,
12
+ :int, :long, :float, :double]
13
+
14
+ JAVA_TYPE_NODES =
15
+ JAVA_TYPES.map { |t| s(:send, s(:const, nil, :Java), t) }
16
+
11
17
  def on_send(node)
18
+ # ignore Java interop code like Java::int
19
+ return if JAVA_TYPE_NODES.include?(node)
20
+
12
21
  receiver, method_name, *_args = *node
13
22
 
14
23
  # discard methods with nil receivers and op methods(like [])
@@ -15,7 +15,7 @@ module RuboCop
15
15
  processed_source.comments.each do |comment|
16
16
  margin, first_word, colon, space, note = split_comment(comment)
17
17
  next unless annotation?(comment) &&
18
- !correct_annotation?(first_word, colon, space, note)
18
+ !correct_annotation?(first_word, colon, space, note)
19
19
 
20
20
  start = comment.loc.expression.begin_pos + margin.length
21
21
  length = first_word.length + (colon || '').length
@@ -10,41 +10,41 @@ module RuboCop
10
10
  MSG = 'Incorrect indentation detected (column %d instead of %d).'
11
11
 
12
12
  def investigate(processed_source)
13
- processed_source.comments.each do |comment|
14
- lines = processed_source.lines
15
- own_line = lines[comment.loc.line - 1]
16
- next unless own_line =~ /\A\s*#/
13
+ processed_source.comments.each { |comment| check(comment) }
14
+ end
17
15
 
18
- next_line =
19
- lines[comment.loc.line..-1].find { |line| !line.blank? }
16
+ private
20
17
 
21
- correct_comment_indentation = correct_indentation(next_line)
22
- column = comment.loc.column
18
+ def check(comment)
19
+ lines = processed_source.lines
20
+ own_line = lines[comment.loc.line - 1]
21
+ return unless own_line =~ /\A\s*#/
23
22
 
24
- @column_delta = correct_comment_indentation - column
25
- next if @column_delta == 0
23
+ next_line = lines[comment.loc.line..-1].find { |line| !line.blank? }
24
+ correct_comment_indentation = correct_indentation(next_line)
25
+ column = comment.loc.column
26
26
 
27
- if two_alternatives?(next_line)
28
- correct_comment_indentation +=
29
- IndentationWidth::CORRECT_INDENTATION # Try the other
30
- # We keep @column_delta unchanged so that autocorrect changes to
31
- # the preferred style of aligning the comment with the keyword.
32
- end
27
+ @column_delta = correct_comment_indentation - column
28
+ return if @column_delta == 0
33
29
 
34
- next if column == correct_comment_indentation
35
- add_offense(comment, comment.loc.expression,
36
- format(MSG, column, correct_comment_indentation))
30
+ if two_alternatives?(next_line)
31
+ # Try the other
32
+ correct_comment_indentation += configured_indentation_width
33
+ # We keep @column_delta unchanged so that autocorrect changes to
34
+ # the preferred style of aligning the comment with the keyword.
37
35
  end
38
- end
39
36
 
40
- private
37
+ return if column == correct_comment_indentation
38
+ add_offense(comment, comment.loc.expression,
39
+ format(MSG, column, correct_comment_indentation))
40
+ end
41
41
 
42
42
  def correct_indentation(next_line)
43
43
  return 0 unless next_line
44
44
 
45
45
  indentation_of_next_line = next_line =~ /\S/
46
46
  indentation_of_next_line + if less_indented?(next_line)
47
- IndentationWidth::CORRECT_INDENTATION
47
+ configured_indentation_width
48
48
  else
49
49
  0
50
50
  end
@@ -7,12 +7,12 @@ module RuboCop
7
7
  # that does not take any arguments. Both instance and
8
8
  # class/singleton methods are checked.
9
9
  class DefWithParentheses < Cop
10
- include OnMethod
10
+ include OnMethodDef
11
11
 
12
12
  MSG = "Omit the parentheses in defs when the method doesn't accept " \
13
13
  'any arguments.'
14
14
 
15
- def on_method(node, _method_name, args, _body)
15
+ def on_method_def(node, _method_name, args, _body)
16
16
  start_line = node.loc.keyword.line
17
17
  end_line = node.loc.end.line
18
18
 
@@ -13,7 +13,7 @@ module RuboCop
13
13
  def on_send(node)
14
14
  _receiver, method_name, *args = *node
15
15
  return unless args.size == 1 &&
16
- DEPRECATED_METHODS.include?(method_name)
16
+ DEPRECATED_METHODS.include?(method_name)
17
17
 
18
18
  add_offense(node, :selector,
19
19
  format(MSG,
@@ -4,7 +4,7 @@ module RuboCop
4
4
  module Cop
5
5
  module Style
6
6
  # This cop checks for uses of double negation (!!) to convert something
7
- # to a boolean value. As this is both cryptic and usually redundant it
7
+ # to a boolean value. As this is both cryptic and usually redundant, it
8
8
  # should be avoided.
9
9
  #
10
10
  # @example
@@ -14,6 +14,11 @@ module RuboCop
14
14
  #
15
15
  # # good
16
16
  # !something.nil?
17
+ #
18
+ # Please, note that when something is a boolean value
19
+ # !!something and !something.nil? are not the same thing.
20
+ # As you're unlikely to write code that can accept values of any type
21
+ # this is rarely a problem in practice.
17
22
  class DoubleNegation < Cop
18
23
  MSG = 'Avoid the use of double negation (`!!`).'
19
24
 
@@ -0,0 +1,93 @@
1
+ # encoding: utf-8
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Style
6
+ # This cops checks the alignment of else keywords. Normally they should
7
+ # be aligned with an if/unless/while/until/begin/def keyword, but there
8
+ # are special cases when they should follow the same rules as the
9
+ # alignment of end.
10
+ class ElseAlignment < Cop
11
+ include AutocorrectAlignment
12
+ include CheckAssignment
13
+
14
+ MSG = 'Align `%s` with `%s`.'
15
+
16
+ def on_if(node, base = nil)
17
+ return if ignored_node?(node)
18
+ return unless node.loc.respond_to?(:else)
19
+ return if node.loc.else.nil?
20
+
21
+ else_range = node.loc.else
22
+ return unless begins_its_line?(else_range)
23
+
24
+ base_range = if base
25
+ base.loc.expression
26
+ else
27
+ base = node
28
+ until %w(if unless).include?(base.loc.keyword.source)
29
+ base = base.parent
30
+ end
31
+ base.loc.keyword
32
+ end
33
+
34
+ check_alignment(base_range, else_range)
35
+ end
36
+
37
+ def on_rescue(node)
38
+ return unless node.loc.else
39
+
40
+ grandparent = node.parent.parent
41
+ base = case node.parent.type
42
+ when :def, :defs
43
+ if grandparent && grandparent.type == :send
44
+ grandparent.loc.selector
45
+ else
46
+ node.parent.loc.keyword
47
+ end
48
+ when :ensure
49
+ grandparent.loc.begin
50
+ else
51
+ node.loc.keyword
52
+ end
53
+ check_alignment(base, node.loc.else)
54
+ end
55
+
56
+ def on_case(node)
57
+ _cond, *whens, _else = *node
58
+ return unless node.loc.else
59
+ check_alignment(whens.last.loc.keyword, node.loc.else)
60
+ end
61
+
62
+ private
63
+
64
+ def check_assignment(node, rhs)
65
+ # If there are method calls chained to the right hand side of the
66
+ # assignment, we let rhs be the receiver of those method calls before
67
+ # we check its indentation.
68
+ rhs = first_part_of_call_chain(rhs)
69
+ return unless rhs
70
+
71
+ end_config = config.for_cop('Lint/EndAlignment')
72
+ style = end_config['Enabled'] ? end_config['AlignWith'] : 'keyword'
73
+ base = style == 'variable' ? node : rhs
74
+
75
+ return if rhs.type != :if
76
+
77
+ on_if(rhs, base)
78
+ ignore_node(rhs)
79
+ end
80
+
81
+ def check_alignment(base_loc, else_range)
82
+ return unless begins_its_line?(else_range)
83
+
84
+ @column_delta = base_loc.column - else_range.column
85
+ return if @column_delta == 0
86
+
87
+ add_offense(else_range, else_range,
88
+ format(MSG, else_range.source, base_loc.source[/^\S*/]))
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end