rubocop 0.27.1 → 0.28.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 (83) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +44 -4
  3. data/Gemfile +1 -1
  4. data/README.md +16 -1
  5. data/config/default.yml +15 -1
  6. data/config/disabled.yml +5 -0
  7. data/config/enabled.yml +10 -2
  8. data/lib/rubocop.rb +3 -0
  9. data/lib/rubocop/config.rb +1 -1
  10. data/lib/rubocop/cop/mixin/access_modifier_node.rb +2 -2
  11. data/lib/rubocop/cop/mixin/autocorrect_unless_changing_ast.rb +10 -26
  12. data/lib/rubocop/cop/mixin/on_method_def.rb +1 -1
  13. data/lib/rubocop/cop/mixin/string_help.rb +10 -1
  14. data/lib/rubocop/cop/style/align_hash.rb +2 -2
  15. data/lib/rubocop/cop/style/ascii_identifiers.rb +1 -1
  16. data/lib/rubocop/cop/style/braces_around_hash_parameters.rb +21 -19
  17. data/lib/rubocop/cop/style/else_alignment.rb +29 -16
  18. data/lib/rubocop/cop/style/empty_else.rb +47 -0
  19. data/lib/rubocop/cop/style/empty_lines_around_block_body.rb +38 -0
  20. data/lib/rubocop/cop/style/extra_spacing.rb +35 -0
  21. data/lib/rubocop/cop/style/indentation_width.rb +1 -1
  22. data/lib/rubocop/cop/style/leading_comment_space.rb +1 -1
  23. data/lib/rubocop/cop/style/line_end_concatenation.rb +5 -1
  24. data/lib/rubocop/cop/style/multiline_operation_indentation.rb +20 -4
  25. data/lib/rubocop/cop/style/negated_while.rb +3 -1
  26. data/lib/rubocop/cop/style/perl_backrefs.rb +8 -3
  27. data/lib/rubocop/cop/style/single_line_block_params.rb +7 -1
  28. data/lib/rubocop/cop/style/special_global_vars.rb +8 -3
  29. data/lib/rubocop/cop/style/string_literals.rb +4 -11
  30. data/lib/rubocop/cop/style/string_literals_in_interpolation.rb +2 -7
  31. data/lib/rubocop/cop/style/symbol_proc.rb +14 -6
  32. data/lib/rubocop/cop/style/unneeded_capital_w.rb +2 -1
  33. data/lib/rubocop/cop/util.rb +1 -1
  34. data/lib/rubocop/cop/variable_force.rb +3 -3
  35. data/lib/rubocop/cop/variable_force/scope.rb +1 -1
  36. data/lib/rubocop/cop/variable_force/variable.rb +1 -1
  37. data/lib/rubocop/formatter/html_formatter.rb +1 -1
  38. data/lib/rubocop/options.rb +13 -6
  39. data/lib/rubocop/rake_task.rb +0 -1
  40. data/lib/rubocop/runner.rb +19 -6
  41. data/lib/rubocop/target_finder.rb +32 -1
  42. data/lib/rubocop/version.rb +1 -1
  43. data/relnotes/v0.28.0.md +90 -0
  44. data/spec/project_spec.rb +1 -0
  45. data/spec/rubocop/cli_spec.rb +115 -24
  46. data/spec/rubocop/comment_config_spec.rb +1 -1
  47. data/spec/rubocop/cop/lint/assignment_in_condition_spec.rb +0 -1
  48. data/spec/rubocop/cop/lint/block_alignment_spec.rb +4 -4
  49. data/spec/rubocop/cop/lint/unused_method_argument_spec.rb +1 -1
  50. data/spec/rubocop/cop/lint/useless_assignment_spec.rb +2 -3
  51. data/spec/rubocop/cop/lint/useless_setter_call_spec.rb +1 -1
  52. data/spec/rubocop/cop/lint/void_spec.rb +0 -1
  53. data/spec/rubocop/cop/style/access_modifier_indentation_spec.rb +2 -2
  54. data/spec/rubocop/cop/style/blocks_spec.rb +8 -0
  55. data/spec/rubocop/cop/style/braces_around_hash_parameters_spec.rb +196 -215
  56. data/spec/rubocop/cop/style/case_indentation_spec.rb +4 -4
  57. data/spec/rubocop/cop/style/documentation_spec.rb +0 -1
  58. data/spec/rubocop/cop/style/else_alignment_spec.rb +63 -4
  59. data/spec/rubocop/cop/style/empty_else_spec.rb +100 -0
  60. data/spec/rubocop/cop/style/empty_lines_around_block_body_spec.rb +103 -0
  61. data/spec/rubocop/cop/style/empty_lines_around_method_body_spec.rb +1 -1
  62. data/spec/rubocop/cop/style/end_of_line_spec.rb +2 -2
  63. data/spec/rubocop/cop/style/extra_spacing_spec.rb +68 -0
  64. data/spec/rubocop/cop/style/leading_comment_space_spec.rb +5 -0
  65. data/spec/rubocop/cop/style/line_end_concatenation_spec.rb +8 -0
  66. data/spec/rubocop/cop/style/multiline_operation_indentation_spec.rb +35 -2
  67. data/spec/rubocop/cop/style/negated_if_spec.rb +1 -1
  68. data/spec/rubocop/cop/style/negated_while_spec.rb +5 -3
  69. data/spec/rubocop/cop/style/percent_q_literals_spec.rb +1 -1
  70. data/spec/rubocop/cop/style/perl_backrefs_spec.rb +5 -0
  71. data/spec/rubocop/cop/style/signal_exception_spec.rb +0 -1
  72. data/spec/rubocop/cop/style/single_line_block_params_spec.rb +13 -1
  73. data/spec/rubocop/cop/style/special_global_vars_spec.rb +5 -0
  74. data/spec/rubocop/cop/style/string_literals_spec.rb +11 -1
  75. data/spec/rubocop/cop/style/symbol_proc_spec.rb +20 -1
  76. data/spec/rubocop/cop/style/tab_spec.rb +2 -2
  77. data/spec/rubocop/cop/style/trailing_comma_spec.rb +1 -1
  78. data/spec/rubocop/cop/style/unneeded_capital_w_spec.rb +5 -0
  79. data/spec/rubocop/cop/team_spec.rb +2 -2
  80. data/spec/rubocop/formatter/offense_count_formatter_spec.rb +0 -1
  81. data/spec/rubocop/options_spec.rb +2 -0
  82. data/spec/rubocop/target_finder_spec.rb +23 -2
  83. metadata +12 -2
@@ -21,27 +21,28 @@ module RuboCop
21
21
  else_range = node.loc.else
22
22
  return unless begins_its_line?(else_range)
23
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)
24
+ check_alignment(base_range(node, base), else_range)
25
+
26
+ return if else_range.source != 'elsif'
27
+
28
+ # If the `else` part is actually an `elsif`, we check the `elsif`
29
+ # node in case it contains an `else` within, because that `else`
30
+ # should have the same alignment (base).
31
+ _condition, _if_body, else_body = *node
32
+ on_if(else_body, base)
33
+ # The `elsif` node will get an `on_if` call from the framework later,
34
+ # but we're done here, so we set it to ignored.
35
+ ignore_node(else_body)
35
36
  end
36
37
 
37
38
  def on_rescue(node)
38
39
  return unless node.loc.else
39
40
 
40
41
  parent = node.parent
42
+ parent = parent.parent if parent.type == :ensure
41
43
  base = case parent.type
42
44
  when :def, :defs then base_for_method_definition(parent)
43
- when :kwbegin then parent.loc.begin
44
- when :ensure then parent.parent.loc.begin
45
+ when :kwbegin then parent.loc.begin
45
46
  else node.loc.keyword
46
47
  end
47
48
  check_alignment(base, node.loc.else)
@@ -55,6 +56,18 @@ module RuboCop
55
56
 
56
57
  private
57
58
 
59
+ def base_range(node, base)
60
+ if base
61
+ base.loc.expression
62
+ else
63
+ base = node
64
+ until %w(if unless).include?(base.loc.keyword.source)
65
+ base = base.parent
66
+ end
67
+ base.loc.keyword
68
+ end
69
+ end
70
+
58
71
  def base_for_method_definition(node)
59
72
  parent = node.parent
60
73
  if parent && parent.type == :send
@@ -81,14 +94,14 @@ module RuboCop
81
94
  ignore_node(rhs)
82
95
  end
83
96
 
84
- def check_alignment(base_loc, else_range)
97
+ def check_alignment(base_range, else_range)
85
98
  return unless begins_its_line?(else_range)
86
99
 
87
- @column_delta = base_loc.column - else_range.column
100
+ @column_delta = base_range.column - else_range.column
88
101
  return if @column_delta == 0
89
102
 
90
103
  add_offense(else_range, else_range,
91
- format(MSG, else_range.source, base_loc.source[/^\S*/]))
104
+ format(MSG, else_range.source, base_range.source[/^\S*/]))
92
105
  end
93
106
  end
94
107
  end
@@ -0,0 +1,47 @@
1
+ # encoding: utf-8
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Style
6
+ # Checks for empty else-clauses, possibly including comments and/or an
7
+ # explicit `nil`.
8
+ class EmptyElse < Cop
9
+ include OnNormalIfUnless
10
+
11
+ MSG = 'Redundant empty `else`-clause.'
12
+
13
+ def on_normal_if_unless(node)
14
+ check(node, if_else_clause(node))
15
+ end
16
+
17
+ def on_case(node)
18
+ check(node, case_else_clause(node))
19
+ end
20
+
21
+ private
22
+
23
+ def check(node, else_clause)
24
+ return unless node.loc.else
25
+ return if else_clause && else_clause.type != :nil
26
+
27
+ add_offense(node, :else, MSG)
28
+ end
29
+
30
+ def if_else_clause(node)
31
+ keyword = node.loc.keyword
32
+ if keyword.is?('if')
33
+ node.children[2]
34
+ elsif keyword.is?('elsif')
35
+ node.children[2]
36
+ elsif keyword.is?('unless')
37
+ node.children[1]
38
+ end
39
+ end
40
+
41
+ def case_else_clause(node)
42
+ node.children.last
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,38 @@
1
+ # encoding: utf-8
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Style
6
+ # This cops checks if empty lines around the bodies of blocks match
7
+ # the configuration.
8
+ #
9
+ # @example
10
+ #
11
+ # something do
12
+ #
13
+ # ...
14
+ # end
15
+ #
16
+ class EmptyLinesAroundBlockBody < Cop
17
+ include EmptyLinesAroundBody
18
+
19
+ KIND = 'block'
20
+
21
+ def on_block(node)
22
+ check(node)
23
+ end
24
+
25
+ private
26
+
27
+ def check(node)
28
+ start_line = node.loc.begin.line
29
+ end_line = node.loc.end.line
30
+
31
+ return if start_line == end_line
32
+
33
+ check_source(start_line, end_line)
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,35 @@
1
+ # encoding: utf-8
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Style
6
+ # This cop checks for extra/unnecessary whitespace.
7
+ #
8
+ # @example
9
+ #
10
+ # name = "RuboCop"
11
+ # website = "https://github.com/bbatsov/rubocop"
12
+ class ExtraSpacing < Cop
13
+ MSG = 'Unnecessary spacing detected.'
14
+
15
+ def investigate(processed_source)
16
+ processed_source.tokens.each_cons(2) do |t1, t2|
17
+ next unless t1.pos.line == t2.pos.line
18
+ next unless t2.pos.begin_pos - 1 > t1.pos.end_pos
19
+ buffer = processed_source.buffer
20
+ start_pos = t1.pos.end_pos
21
+ end_pos = t2.pos.begin_pos - 1
22
+ range = Parser::Source::Range.new(buffer, start_pos, end_pos)
23
+ add_offense(range, range, MSG)
24
+ end
25
+ end
26
+
27
+ def autocorrect(range)
28
+ @corrections << lambda do |corrector|
29
+ corrector.remove(range)
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -94,7 +94,7 @@ module RuboCop
94
94
  latest_when = nil
95
95
  branches.compact.each do |b|
96
96
  if b.type == :when
97
- # TODO: Revert to the original expresson once the fix in Rubinius
97
+ # TODO: Revert to the original expression once the fix in Rubinius
98
98
  # is released.
99
99
  #
100
100
  # Originally this expression was:
@@ -12,7 +12,7 @@ module RuboCop
12
12
 
13
13
  def investigate(processed_source)
14
14
  processed_source.comments.each do |comment|
15
- next unless comment.text =~ /^#+[^#\s:+-]/
15
+ next unless comment.text =~ /^#+[^#\s=:+-]/
16
16
  next if comment.text.start_with?('#!') && comment.loc.line == 1
17
17
 
18
18
  add_offense(comment, :expression)
@@ -63,7 +63,11 @@ module RuboCop
63
63
  return false unless node.loc.respond_to?(:begin)
64
64
 
65
65
  # we care only about quotes-delimited literals
66
- node.loc.begin && ["'", '"'].include?(node.loc.begin.source)
66
+ if node.loc.begin
67
+ ["'", '"'].include?(node.loc.begin.source)
68
+ elsif node.children.any?
69
+ node.children.map { |child| string_type?(child) }.all?
70
+ end
67
71
  end
68
72
 
69
73
  def final_node_is_string_type?(node)
@@ -12,7 +12,7 @@ module RuboCop
12
12
  # b
13
13
  # something
14
14
  # end
15
- class MultilineOperationIndentation < Cop
15
+ class MultilineOperationIndentation < Cop # rubocop:disable ClassLength
16
16
  include ConfigurableEnforcedStyle
17
17
  include AutocorrectAlignment
18
18
 
@@ -51,7 +51,9 @@ module RuboCop
51
51
 
52
52
  def incorrect_style_detected(range, node, lhs, rhs)
53
53
  add_offense(range, range, message(node, lhs, rhs)) do
54
- unless offending_range(node, lhs, rhs, alternative_style)
54
+ if offending_range(node, lhs, rhs, alternative_style)
55
+ unrecognized_style_detected
56
+ else
55
57
  opposite_style_detected
56
58
  end
57
59
  end
@@ -105,7 +107,11 @@ module RuboCop
105
107
  # d <-- d is indented relative to a
106
108
  def left_hand_side(receiver)
107
109
  lhs = receiver
108
- lhs = lhs.parent while lhs.parent && lhs.parent.type == :send
110
+ while lhs.parent && lhs.parent.type == :send
111
+ _receiver, method_name, *_args = *lhs.parent
112
+ break if operator?(method_name)
113
+ lhs = lhs.parent
114
+ end
109
115
  lhs
110
116
  end
111
117
 
@@ -151,7 +157,17 @@ module RuboCop
151
157
  end
152
158
 
153
159
  def assignment?(node)
154
- node.each_ancestor.find { |a| ASGN_NODES.include?(a.type) }
160
+ node.each_ancestor.find do |a|
161
+ case a.type
162
+ when :send
163
+ _receiver, method_name, *_args = *a
164
+ # The []= operator is the only assignment operator that is parsed
165
+ # as a :send node.
166
+ method_name == :[]=
167
+ when *ASGN_NODES
168
+ true
169
+ end
170
+ end
155
171
  end
156
172
 
157
173
  def not_for_this_cop?(node)
@@ -30,7 +30,9 @@ module RuboCop
30
30
  def autocorrect(node)
31
31
  @corrections << lambda do |corrector|
32
32
  condition, _body, _rest = *node
33
- # unwrap the negated portion of the condition (a send node)
33
+ # Look inside parentheses around the condition, if any.
34
+ condition, _ = *condition while condition.type == :begin
35
+ # Unwrap the negated portion of the condition (a send node).
34
36
  pos_condition, _method, = *condition
35
37
  corrector.replace(
36
38
  node.loc.keyword,
@@ -15,9 +15,14 @@ module RuboCop
15
15
  def autocorrect(node)
16
16
  @corrections << lambda do |corrector|
17
17
  backref, = *node
18
-
19
- corrector.replace(node.loc.expression,
20
- "Regexp.last_match[#{backref}]")
18
+ parent_type = node.parent ? node.parent.type : nil
19
+ if [:dstr, :xstr, :regexp].include?(parent_type)
20
+ corrector.replace(node.loc.expression,
21
+ "{Regexp.last_match[#{backref}]}")
22
+ else
23
+ corrector.replace(node.loc.expression,
24
+ "Regexp.last_match[#{backref}]")
25
+ end
21
26
  end
22
27
  end
23
28
  end
@@ -53,7 +53,13 @@ module RuboCop
53
53
  def args_match?(method_name, args)
54
54
  actual_args = args.flat_map(&:to_a)
55
55
 
56
- actual_args == target_args(method_name).map(&:to_sym)
56
+ # Prepending an underscore to mark an unused parameter is allowed, so
57
+ # we remove any leading underscores before comparing.
58
+ actual_args_no_underscores = actual_args.map do |arg|
59
+ arg.to_s.sub(/^_+/, '')
60
+ end
61
+
62
+ actual_args_no_underscores == target_args(method_name)
57
63
  end
58
64
  end
59
65
  end
@@ -73,9 +73,14 @@ module RuboCop
73
73
  def autocorrect(node)
74
74
  @corrections << lambda do |corrector|
75
75
  global_var, = *node
76
-
77
- corrector.replace(node.loc.expression,
78
- PREFERRED_VARS[global_var].first)
76
+ parent_type = node.parent ? node.parent.type : nil
77
+ if [:dstr, :xstr, :regexp].include?(parent_type)
78
+ corrector.replace(node.loc.expression,
79
+ "{#{PREFERRED_VARS[global_var].first}}")
80
+ else
81
+ corrector.replace(node.loc.expression,
82
+ PREFERRED_VARS[global_var].first)
83
+ end
79
84
  end
80
85
  end
81
86
  end
@@ -8,17 +8,6 @@ module RuboCop
8
8
  include ConfigurableEnforcedStyle
9
9
  include StringLiteralsHelp
10
10
 
11
- def on_dstr(node)
12
- # A dstr node with dstr and str children is a concatenated
13
- # string. Don't ignore the whole thing.
14
- return if node.children.find { |child| child.type == :str }
15
-
16
- # Dynamic strings can not use single quotes, and quotes inside
17
- # interpolation expressions are checked by the
18
- # StringLiteralsInInterpolation cop, so ignore.
19
- ignore_node(node)
20
- end
21
-
22
11
  private
23
12
 
24
13
  def message(*)
@@ -32,6 +21,10 @@ module RuboCop
32
21
  end
33
22
 
34
23
  def offense?(node)
24
+ # If it's a string within an interpolation, then it's not an offense
25
+ # for this cop.
26
+ return false if inside_interpolation?(node)
27
+
35
28
  wrong_quotes?(node, style)
36
29
  end
37
30
  end
@@ -19,13 +19,8 @@ module RuboCop
19
19
 
20
20
  def offense?(node)
21
21
  # If it's not a string within an interpolation, then it's not an
22
- # offense for this cop. A :begin node inside a :dstr node is an
23
- # interpolation.
24
- begin_found = false
25
- return false unless node.each_ancestor.find do |a|
26
- begin_found = true if a.type == :begin
27
- begin_found && a.type == :dstr
28
- end
22
+ # offense for this cop.
23
+ return false unless inside_interpolation?(node)
29
24
 
30
25
  wrong_quotes?(node, style)
31
26
  end
@@ -14,13 +14,18 @@ module RuboCop
14
14
  class SymbolProc < Cop
15
15
  MSG = 'Pass `&:%s` as an argument to `%s` instead of a block.'
16
16
 
17
+ PROC_NODE = s(:send, s(:const, nil, :Proc), :new)
18
+
17
19
  def on_block(node)
18
20
  block_send, block_args, block_body = *node
19
21
 
20
22
  _breceiver, bmethod_name, bargs = *block_send
21
23
 
22
- # we should ignore lambdas
23
- return if bmethod_name == :lambda
24
+ # TODO: Rails-specific handling that we should probably make
25
+ # configurable - https://github.com/bbatsov/rubocop/issues/1485
26
+ # we should ignore lambdas & procs
27
+ return if block_send == PROC_NODE
28
+ return if [:lambda, :proc].include?(bmethod_name)
24
29
  return if ignored_method?(bmethod_name)
25
30
  # File.open(file) { |f| f.readlines }
26
31
  return if bargs
@@ -36,13 +41,16 @@ module RuboCop
36
41
 
37
42
  def autocorrect(node)
38
43
  @corrections << lambda do |corrector|
39
- block_method, _block_args, block_body = *node
44
+ _block_method, _block_args, block_body = *node
40
45
  _receiver, method_name, _args = *block_body
41
46
 
42
- replacement = "#{block_method.loc.expression.source}" \
43
- "(&:#{method_name})"
47
+ block_range =
48
+ Parser::Source::Range.new(node.loc.expression.source_buffer,
49
+ node.loc.begin.begin_pos,
50
+ node.loc.end.end_pos)
44
51
 
45
- corrector.replace(node.loc.expression, replacement)
52
+ corrector.replace(range_with_surrounding_space(block_range, :left),
53
+ "(&:#{method_name})")
46
54
  end
47
55
  end
48
56
 
@@ -28,7 +28,8 @@ module RuboCop
28
28
 
29
29
  def autocorrect(node)
30
30
  @corrections << lambda do |corrector|
31
- corrector.replace(node.loc.begin, '%w(')
31
+ src = node.loc.begin.source
32
+ corrector.replace(node.loc.begin, src.tr('W', 'w'))
32
33
  end
33
34
  end
34
35
  end