rubocop 0.24.1 → 0.25.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 (128) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop_todo.yml +12 -8
  3. data/.travis.yml +1 -1
  4. data/CHANGELOG.md +42 -0
  5. data/Gemfile +2 -0
  6. data/README.md +27 -6
  7. data/bin/rubocop +10 -15
  8. data/config/default.yml +72 -25
  9. data/config/enabled.yml +57 -25
  10. data/lib/rubocop.rb +15 -8
  11. data/lib/rubocop/config_loader.rb +11 -7
  12. data/lib/rubocop/cop/cop.rb +16 -16
  13. data/lib/rubocop/cop/ignored_node.rb +11 -4
  14. data/lib/rubocop/cop/lint/block_alignment.rb +29 -4
  15. data/lib/rubocop/cop/lint/debugger.rb +8 -1
  16. data/lib/rubocop/cop/lint/def_end_alignment.rb +5 -1
  17. data/lib/rubocop/cop/lint/end_alignment.rb +5 -5
  18. data/lib/rubocop/cop/lint/end_in_method.rb +2 -2
  19. data/lib/rubocop/cop/lint/useless_setter_call.rb +2 -2
  20. data/lib/rubocop/cop/{style → metrics}/block_nesting.rb +1 -1
  21. data/lib/rubocop/cop/{style → metrics}/class_length.rb +4 -4
  22. data/lib/rubocop/cop/{style → metrics}/cyclomatic_complexity.rb +5 -16
  23. data/lib/rubocop/cop/{style → metrics}/line_length.rb +1 -1
  24. data/lib/rubocop/cop/{style → metrics}/method_length.rb +8 -4
  25. data/lib/rubocop/cop/{style → metrics}/parameter_lists.rb +1 -1
  26. data/lib/rubocop/cop/metrics/perceived_complexity.rb +61 -0
  27. data/lib/rubocop/cop/mixin/autocorrect_unless_changing_ast.rb +10 -2
  28. data/lib/rubocop/cop/mixin/code_length.rb +2 -3
  29. data/lib/rubocop/cop/mixin/configurable_naming.rb +6 -20
  30. data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +1 -1
  31. data/lib/rubocop/cop/mixin/if_node.rb +1 -1
  32. data/lib/rubocop/cop/mixin/method_complexity.rb +32 -0
  33. data/lib/rubocop/cop/mixin/negative_conditional.rb +1 -1
  34. data/lib/rubocop/cop/mixin/{check_methods.rb → on_method.rb} +3 -3
  35. data/lib/rubocop/cop/mixin/on_normal_if_unless.rb +24 -0
  36. data/lib/rubocop/cop/mixin/percent_literal.rb +2 -1
  37. data/lib/rubocop/cop/mixin/space_inside.rb +33 -4
  38. data/lib/rubocop/cop/mixin/statement_modifier.rb +14 -14
  39. data/lib/rubocop/cop/mixin/string_help.rb +4 -0
  40. data/lib/rubocop/cop/mixin/surrounding_space.rb +1 -0
  41. data/lib/rubocop/cop/rails/delegate.rb +2 -2
  42. data/lib/rubocop/cop/rails/output.rb +4 -2
  43. data/lib/rubocop/cop/style/accessor_method_name.rb +2 -2
  44. data/lib/rubocop/cop/style/align_hash.rb +9 -1
  45. data/lib/rubocop/cop/style/and_or.rb +37 -3
  46. data/lib/rubocop/cop/style/bare_percent_literals.rb +46 -0
  47. data/lib/rubocop/cop/style/block_end_newline.rb +56 -0
  48. data/lib/rubocop/cop/style/character_literal.rb +1 -1
  49. data/lib/rubocop/cop/style/def_with_parentheses.rb +2 -2
  50. data/lib/rubocop/cop/style/empty_lines_around_access_modifier.rb +31 -3
  51. data/lib/rubocop/cop/style/empty_lines_around_body.rb +6 -2
  52. data/lib/rubocop/cop/style/end_of_line.rb +3 -14
  53. data/lib/rubocop/cop/style/if_unless_modifier.rb +3 -6
  54. data/lib/rubocop/cop/style/if_with_semicolon.rb +6 -7
  55. data/lib/rubocop/cop/style/indentation_width.rb +3 -8
  56. data/lib/rubocop/cop/style/method_def_parentheses.rb +2 -2
  57. data/lib/rubocop/cop/style/method_name.rb +4 -18
  58. data/lib/rubocop/cop/style/multiline_block_layout.rb +73 -0
  59. data/lib/rubocop/cop/style/multiline_if_then.rb +4 -4
  60. data/lib/rubocop/cop/style/negated_if.rb +1 -1
  61. data/lib/rubocop/cop/style/negated_while.rb +2 -2
  62. data/lib/rubocop/cop/style/next.rb +12 -0
  63. data/lib/rubocop/cop/style/one_line_conditional.rb +6 -6
  64. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +22 -8
  65. data/lib/rubocop/cop/style/percent_q_literals.rb +53 -0
  66. data/lib/rubocop/cop/style/predicate_name.rb +2 -2
  67. data/lib/rubocop/cop/style/redundant_begin.rb +2 -2
  68. data/lib/rubocop/cop/style/redundant_return.rb +2 -2
  69. data/lib/rubocop/cop/style/rescue_modifier.rb +7 -3
  70. data/lib/rubocop/cop/style/single_line_methods.rb +2 -2
  71. data/lib/rubocop/cop/style/space_after_method_name.rb +2 -2
  72. data/lib/rubocop/cop/style/space_inside_block_braces.rb +14 -10
  73. data/lib/rubocop/cop/style/space_inside_brackets.rb +5 -1
  74. data/lib/rubocop/cop/style/string_literals.rb +5 -8
  75. data/lib/rubocop/cop/style/trailing_comma.rb +15 -3
  76. data/lib/rubocop/cop/style/trivial_accessors.rb +2 -2
  77. data/lib/rubocop/cop/style/unneeded_capital_w.rb +2 -4
  78. data/lib/rubocop/cop/style/unneeded_percent_q.rb +13 -0
  79. data/lib/rubocop/cop/style/variable_interpolation.rb +14 -2
  80. data/lib/rubocop/cop/style/variable_name.rb +17 -17
  81. data/lib/rubocop/cop/style/while_until_modifier.rb +2 -5
  82. data/lib/rubocop/cop/util.rb +5 -0
  83. data/lib/rubocop/cop/variable_force.rb +7 -6
  84. data/lib/rubocop/formatter/base_formatter.rb +2 -2
  85. data/lib/rubocop/processed_source.rb +5 -22
  86. data/lib/rubocop/version.rb +1 -1
  87. data/relnotes/v0.25.0.md +91 -0
  88. data/rubocop.gemspec +2 -3
  89. data/spec/project_spec.rb +1 -1
  90. data/spec/rubocop/cli_spec.rb +70 -44
  91. data/spec/rubocop/comment_config_spec.rb +6 -6
  92. data/spec/rubocop/config_loader_spec.rb +19 -13
  93. data/spec/rubocop/config_spec.rb +3 -3
  94. data/spec/rubocop/cop/commissioner_spec.rb +1 -1
  95. data/spec/rubocop/cop/cop_spec.rb +3 -3
  96. data/spec/rubocop/cop/lint/block_alignment_spec.rb +113 -6
  97. data/spec/rubocop/cop/lint/debugger_spec.rb +10 -6
  98. data/spec/rubocop/cop/lint/useless_assignment_spec.rb +12 -0
  99. data/spec/rubocop/cop/{style → metrics}/block_nesting_spec.rb +1 -1
  100. data/spec/rubocop/cop/{style → metrics}/class_length_spec.rb +1 -1
  101. data/spec/rubocop/cop/{style → metrics}/cyclomatic_complexity_spec.rb +1 -1
  102. data/spec/rubocop/cop/{style → metrics}/if_unless_modifier_spec.rb +2 -2
  103. data/spec/rubocop/cop/{style → metrics}/line_length_spec.rb +7 -7
  104. data/spec/rubocop/cop/{style → metrics}/method_length_spec.rb +1 -1
  105. data/spec/rubocop/cop/{style → metrics}/parameter_lists_spec.rb +1 -1
  106. data/spec/rubocop/cop/metrics/perceived_complexity_spec.rb +222 -0
  107. data/spec/rubocop/cop/{style → metrics}/while_until_modifier_spec.rb +2 -2
  108. data/spec/rubocop/cop/rails/output_spec.rb +8 -2
  109. data/spec/rubocop/cop/style/align_hash_spec.rb +7 -0
  110. data/spec/rubocop/cop/style/and_or_spec.rb +245 -43
  111. data/spec/rubocop/cop/style/bare_percent_literals_spec.rb +132 -0
  112. data/spec/rubocop/cop/style/block_end_newline_spec.rb +61 -0
  113. data/spec/rubocop/cop/style/empty_lines_around_access_modifier_spec.rb +34 -0
  114. data/spec/rubocop/cop/style/end_of_line_spec.rb +8 -0
  115. data/spec/rubocop/cop/style/guard_clause_spec.rb +1 -1
  116. data/spec/rubocop/cop/style/multiline_block_layout_spec.rb +138 -0
  117. data/spec/rubocop/cop/style/next_spec.rb +32 -3
  118. data/spec/rubocop/cop/style/percent_literal_delimiters_spec.rb +34 -0
  119. data/spec/rubocop/cop/style/percent_q_literals_spec.rb +122 -0
  120. data/spec/rubocop/cop/style/space_inside_block_braces_spec.rb +20 -0
  121. data/spec/rubocop/cop/style/space_inside_brackets_spec.rb +26 -2
  122. data/spec/rubocop/cop/style/trailing_comma_spec.rb +112 -0
  123. data/spec/rubocop/cop/style/unneeded_percent_q_spec.rb +86 -31
  124. data/spec/rubocop/cop/style/variable_interpolation_spec.rb +21 -1
  125. data/spec/rubocop/cop/team_spec.rb +14 -9
  126. data/spec/spec_helper.rb +1 -0
  127. metadata +47 -50
  128. data/lib/rubocop/cop/mixin/if_then_else.rb +0 -23
@@ -8,7 +8,11 @@ module RuboCop
8
8
  include SpaceInside
9
9
 
10
10
  def specifics
11
- [:tLBRACK, :tRBRACK, 'square brackets']
11
+ [
12
+ [:tLBRACK, :tLBRACK2],
13
+ :tRBRACK,
14
+ 'square brackets'
15
+ ]
12
16
  end
13
17
  end
14
18
  end
@@ -23,14 +23,11 @@ module RuboCop
23
23
  def offense?(node)
24
24
  src = node.loc.expression.source
25
25
  return false if src =~ /^(%[qQ]?|\?|<<-)/i
26
- src !~ if style == :single_quotes
27
- # regex matches IF there is a ' or there is a \\ in the
28
- # string that is not preceeded/followed by another \\
29
- # (e.g. "\\x34") but not "\\\\"
30
- /' | (?<! \\) \\{2}* \\ (?! \\)/x
31
- else
32
- /" | \\/x
33
- end
26
+ if style == :single_quotes
27
+ src !~ /'/ && src !~ StringHelp::ESCAPED_CHAR_REGEXP
28
+ else
29
+ src !~ /" | \\/x
30
+ end
34
31
  end
35
32
 
36
33
  def autocorrect(node)
@@ -121,20 +121,32 @@ module RuboCop
121
121
  range = Parser::Source::Range.new(sb, comma_begin_pos,
122
122
  comma_begin_pos + 1)
123
123
  article = kind =~ /array/ ? 'an' : 'a'
124
- add_offense(nil, range,
124
+ add_offense(range, range,
125
125
  format(MSG, 'Avoid', format(kind, article)) +
126
126
  extra_info + '.')
127
127
  end
128
128
 
129
129
  def put_comma(items, kind, sb)
130
- last_expr = items.last.loc.expression
130
+ last_item = items.last
131
+ return if last_item.type == :block_pass
132
+
133
+ last_expr = last_item.loc.expression
131
134
  ix = last_expr.source.rindex("\n") || 0
132
135
  ix += last_expr.source[ix..-1] =~ /\S/
133
136
  range = Parser::Source::Range.new(sb, last_expr.begin_pos + ix,
134
137
  last_expr.end_pos)
135
- add_offense(nil, range,
138
+ add_offense(range, range,
136
139
  format(MSG, 'Put a', format(kind, 'a multiline') + '.'))
137
140
  end
141
+
142
+ def autocorrect(range)
143
+ @corrections << lambda do |corrector|
144
+ case range.source
145
+ when ',' then corrector.remove(range)
146
+ else corrector.insert_after(range, ',')
147
+ end
148
+ end
149
+ end
138
150
  end
139
151
  end
140
152
  end
@@ -6,13 +6,13 @@ module RuboCop
6
6
  # This cop looks for trivial reader/writer methods, that could
7
7
  # have been created with the attr_* family of functions automatically.
8
8
  class TrivialAccessors < Cop
9
- include CheckMethods
9
+ include OnMethod
10
10
 
11
11
  MSG = 'Use `attr_%s` to define trivial %s methods.'
12
12
 
13
13
  private
14
14
 
15
- def check(node, method_name, args, body)
15
+ def on_method(node, method_name, args, body)
16
16
  kind = if trivial_reader?(method_name, args, body)
17
17
  'reader'
18
18
  elsif trivial_writer?(method_name, args, body)
@@ -16,10 +16,8 @@ module RuboCop
16
16
 
17
17
  private
18
18
 
19
- def on_percent_literal(node, types)
20
- type = type(node)
21
- return unless types.include?(type) &&
22
- node.children.none? { |x| x.type == :dstr }
19
+ def on_percent_literal(node)
20
+ return unless node.children.none? { |x| x.type == :dstr }
23
21
 
24
22
  add_offense(node, :expression)
25
23
  end
@@ -17,12 +17,25 @@ module RuboCop
17
17
  check(node)
18
18
  end
19
19
 
20
+ # We process regexp nodes because the inner str nodes can cause
21
+ # confusion in on_str if they start with %( or %Q(.
22
+ def on_regexp(node)
23
+ string_parts = node.children.select { |child| child.type == :str }
24
+ string_parts.each { |s| ignore_node(s) }
25
+ end
26
+
20
27
  private
21
28
 
22
29
  def check(node)
30
+ if node.loc.respond_to?(:heredoc_body)
31
+ ignore_node(node)
32
+ return
33
+ end
34
+ return if ignored_node?(node) || part_of_ignored_node?(node)
23
35
  src = node.loc.expression.source
24
36
  return unless src =~ /^%q/i
25
37
  return if src =~ /'/ && src =~ /"/
38
+ return if src =~ StringHelp::ESCAPED_CHAR_REGEXP
26
39
 
27
40
  extra = if src =~ /^%Q/
28
41
  ', or for dynamic strings that contain double quotes'
@@ -8,6 +8,20 @@ module RuboCop
8
8
  MSG = 'Replace interpolated variable `%s` with expression `#{%s}`.'
9
9
 
10
10
  def on_dstr(node)
11
+ check_for_interpolation(node)
12
+ end
13
+
14
+ def on_regexp(node)
15
+ check_for_interpolation(node)
16
+ end
17
+
18
+ def on_xstr(node)
19
+ check_for_interpolation(node)
20
+ end
21
+
22
+ private
23
+
24
+ def check_for_interpolation(node)
11
25
  var_nodes(node.children).each do |v|
12
26
  var = v.loc.expression.source
13
27
 
@@ -15,8 +29,6 @@ module RuboCop
15
29
  end
16
30
  end
17
31
 
18
- private
19
-
20
32
  def autocorrect(node)
21
33
  @corrections << lambda do |corrector|
22
34
  expr = node.loc.expression
@@ -9,35 +9,35 @@ module RuboCop
9
9
  include ConfigurableNaming
10
10
 
11
11
  def on_lvasgn(node)
12
- check(node, name_of_variable(node))
12
+ name, = *node
13
+ check_name(node, name, node.loc.name)
13
14
  end
14
15
 
15
16
  def on_ivasgn(node)
16
- check(node, name_of_variable(node))
17
+ name, = *node
18
+ check_name(node, name, node.loc.name)
17
19
  end
18
20
 
21
+ # TODO: Why is this checking invocations of setter rather than
22
+ # definitions? Also, this is not variable.
19
23
  def on_send(node)
20
- check(node, name_of_setter(node))
24
+ return unless setter_call_on_self?(node)
25
+ _receiver, method_name, = *node
26
+ attribute_name = method_name.to_s.sub(/=$/, '').to_sym
27
+ check_name(node, attribute_name, node.loc.selector)
21
28
  end
22
29
 
23
- def name_of_variable(vasgn_node)
24
- expr = vasgn_node.loc.expression
25
- name = vasgn_node.children.first
26
- Parser::Source::Range.new(expr.source_buffer, expr.begin_pos,
27
- expr.begin_pos + name.length)
28
- end
29
-
30
- def name_of_setter(send_node)
31
- receiver, method_name = *send_node
32
- return unless receiver && receiver.type == :self
33
- return unless method_name.to_s.end_with?('=')
34
- after_dot(send_node, method_name.length - '='.length,
35
- Regexp.escape(receiver.loc.expression.source))
36
- end
30
+ private
37
31
 
38
32
  def message(style)
39
33
  format('Use %s for variables.', style)
40
34
  end
35
+
36
+ def setter_call_on_self?(send_node)
37
+ receiver, method_name, = *send_node
38
+ return false unless receiver && receiver.type == :self
39
+ method_name.to_s.end_with?('=')
40
+ end
41
41
  end
42
42
  end
43
43
  end
@@ -14,11 +14,8 @@ module RuboCop
14
14
  on_node([:while, :until], processed_source.ast) do |node|
15
15
  # discard modifier while/until
16
16
  next unless node.loc.end
17
-
18
- if check(node, processed_source.comments)
19
- add_offense(node, :keyword,
20
- message(node.loc.keyword.source))
21
- end
17
+ next unless fit_within_line_as_modifier_form?(node)
18
+ add_offense(node, :keyword, message(node.loc.keyword.source))
22
19
  end
23
20
  end
24
21
 
@@ -153,6 +153,11 @@ module RuboCop
153
153
  Parser::Source::Range.new(@processed_source.buffer, begin_pos, end_pos)
154
154
  end
155
155
 
156
+ def begins_its_line?(range)
157
+ source_before_end = range.source_buffer.source[0...range.begin_pos]
158
+ source_before_end =~ /\n\s*\Z/
159
+ end
160
+
156
161
  # Returns, for example, a bare `if` node if the given node is an `if`
157
162
  # with calls chained to the end of it.
158
163
  def first_part_of_call_chain(node)
@@ -22,7 +22,7 @@ module RuboCop
22
22
  #
23
23
  # def after_declaring_variable(variable, variable_table)
24
24
  # end
25
- class VariableForce < Force # rubocop:disable Style/ClassLength
25
+ class VariableForce < Force # rubocop:disable Metrics/ClassLength
26
26
  VARIABLE_ASSIGNMENT_TYPE = :lvasgn
27
27
  REGEXP_NAMED_CAPTURE_TYPE = :match_with_lvasgn
28
28
  VARIABLE_ASSIGNMENT_TYPES =
@@ -99,7 +99,7 @@ module RuboCop
99
99
  throw :skip_children
100
100
  end
101
101
 
102
- # rubocop:disable Style/MethodLength, Style/CyclomaticComplexity
102
+ # rubocop:disable Metrics/MethodLength, Metrics/CyclomaticComplexity
103
103
  def dispatch_node(node)
104
104
  case node.type
105
105
  when *ARGUMENT_DECLARATION_TYPES
@@ -124,16 +124,17 @@ module RuboCop
124
124
  process_scope(node)
125
125
  end
126
126
  end
127
- # rubocop:enable Style/MethodLength, Style/CyclomaticComplexity
127
+ # rubocop:enable Metrics/MethodLength, Metrics/CyclomaticComplexity
128
128
 
129
129
  def process_variable_declaration(node)
130
- # restarg would have no name:
130
+ variable_name = node.children.first
131
+
132
+ # restarg and kwrestarg would have no name:
131
133
  #
132
134
  # def initialize(*)
133
135
  # end
134
- return if node.type == :restarg && node.children.empty?
136
+ return unless variable_name
135
137
 
136
- variable_name = node.children.first
137
138
  variable_table.declare_variable(variable_name, node)
138
139
  end
139
140
 
@@ -1,6 +1,6 @@
1
1
  # encoding: utf-8
2
2
 
3
- # rubocop:disable Style/LineLength, Lint/UnusedMethodArgument
3
+ # rubocop:disable Metrics/LineLength, Lint/UnusedMethodArgument
4
4
 
5
5
  module RuboCop
6
6
  module Formatter
@@ -41,7 +41,7 @@ module RuboCop
41
41
  # * `#finished`
42
42
  #
43
43
  class BaseFormatter
44
- # rubocop:enable Style/LineLength
44
+ # rubocop:enable Metrics/LineLength
45
45
 
46
46
  # @api public
47
47
  #
@@ -5,14 +5,16 @@ module RuboCop
5
5
  # and other information such as disabled lines for cops.
6
6
  # It also provides a convenient way to access source lines.
7
7
  class ProcessedSource
8
+ STRING_SOURCE_NAME = '(string)'
8
9
  attr_reader :path, :buffer, :ast, :comments, :tokens, :diagnostics,
9
- :parser_error
10
+ :parser_error, :raw_source
10
11
 
11
12
  def self.from_file(path)
12
13
  new(File.read(path), path)
13
14
  end
14
15
 
15
16
  def initialize(source, path = nil)
17
+ @raw_source = source
16
18
  @path = path
17
19
  @diagnostics = []
18
20
  parse(source)
@@ -27,21 +29,7 @@ module RuboCop
27
29
  end
28
30
 
29
31
  def lines
30
- if @lines
31
- @lines
32
- else
33
- init_lines
34
- @lines
35
- end
36
- end
37
-
38
- def raw_lines
39
- if @raw_lines
40
- @raw_lines
41
- else
42
- init_lines
43
- @raw_lines
44
- end
32
+ @lines ||= raw_source.lines.map(&:chomp)
45
33
  end
46
34
 
47
35
  def [](*args)
@@ -56,7 +44,7 @@ module RuboCop
56
44
  private
57
45
 
58
46
  def parse(source)
59
- buffer_name = @path || '(string)'
47
+ buffer_name = @path || STRING_SOURCE_NAME
60
48
  @buffer = Parser::Source::Buffer.new(buffer_name, 1)
61
49
 
62
50
  begin
@@ -90,10 +78,5 @@ module RuboCop
90
78
  end
91
79
  end
92
80
  end
93
-
94
- def init_lines
95
- @raw_lines = @buffer.source.lines
96
- @lines = @raw_lines.map(&:chomp)
97
- end
98
81
  end
99
82
  end
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  # This module holds the RuboCop version information.
5
5
  module Version
6
- STRING = '0.24.1'
6
+ STRING = '0.25.0'
7
7
 
8
8
  MSG = '%s (using Parser %s, running on %s %s %s)'
9
9
 
@@ -0,0 +1,91 @@
1
+ This release comes with lots of bug fixes and several new cops (that will likely need bugfixes in the next release :-)).
2
+
3
+ The most notable change in 0.25 is the addition of the `Metrics` namespace. Several `Style` cops have been moved there
4
+ (e.g. `ClassLength`, `MethodLength`, etc).
5
+
6
+ This release also marks the end of us supporting Ruby 1.9.2 - now Ruby 1.9.3+ is required.
7
+
8
+ Below is the list of all the gory details. Enjoy!
9
+
10
+ ### New features
11
+
12
+ * [#1259](https://github.com/bbatsov/rubocop/issues/1259): Allow AndOr cop to autocorrect by adding method call parenthesis. ([@vrthra][])
13
+ * [#1232](https://github.com/bbatsov/rubocop/issues/1232): Add EnforcedStyle option to cop `AndOr` to restrict it to conditionals. ([@vrthra][])
14
+ * [#835](https://github.com/bbatsov/rubocop/issues/835): New cop `PercentQLiterals` checks if use of `%Q` and `%q` matches configuration. ([@jonas054][])
15
+ * [#835](https://github.com/bbatsov/rubocop/issues/835): New cop `BarePercentLiterals` checks if usage of `%()` or `%Q()` matches configuration. ([@jonas054][])
16
+ * [#1079](https://github.com/bbatsov/rubocop/pull/1079): New cop `MultilineBlockLayout` checks if a multiline block has an extpression on the same line as the start of the block. ([@barunio][])
17
+ * [#1217](https://github.com/bbatsov/rubocop/pull/1217): `Style::EmptyLinesAroundAccessModifier` cop does auto-correction. ([@tamird][])
18
+ * [#1220](https://github.com/bbatsov/rubocop/issues/1220): New cop `PerceivedComplexity` is similar to `CyclomaticComplexity`, but reports when methods have a high complexity for a human reader. ([@jonas054][])
19
+ * `Debugger` cop now checks for `binding.pry_remote`. ([@yous][])
20
+ * [#1238](https://github.com/bbatsov/rubocop/issues/1238): Add `MinBodyLength` option to `Next` cop. ([@bbatsov][])
21
+ * [#1241](https://github.com/bbatsov/rubocop/issues/1241): `TrailingComma` cop does auto-correction. ([@yous][])
22
+ * [#1078](https://github.com/bbatsov/rubocop/pull/1078): New cop `BlockEndNewline` checks if the end statement of a multiline block is on its own line. ([@barunio][])
23
+ * [#1078](https://github.com/bbatsov/rubocop/pull/1078): `BlockAlignment` cop does auto-correction. ([@barunio][])
24
+
25
+ ### Changes
26
+
27
+ * [#1220](https://github.com/bbatsov/rubocop/issues/1220): New namespace `Metrics` created and some `Style` cops moved there. ([@jonas054][])
28
+ * Drop support for Ruby 1.9.2 in accordance with [the end of the security maintenance extension](https://www.ruby-lang.org/en/news/2014/07/01/eol-for-1-8-7-and-1-9-2/). ([@yujinakayama][])
29
+
30
+ ### Bugs fixed
31
+
32
+ * [#1251](https://github.com/bbatsov/rubocop/issues/1251): Fix `PercentLiteralDelimiters` auto-correct indentation error. ([@hannestyden][])
33
+ * [#1197](https://github.com/bbatsov/rubocop/issues/1197): Fix false positive for new lambda syntax in `SpaceInsideBlockBraces`. ([@jonas054][])
34
+ * [#1201](https://github.com/bbatsov/rubocop/issues/1201): Fix error at anonymous keyword splat arguments in some variable cops. ([@yujinakayama][])
35
+ * Fix false positive in `UnneededPercentQ` for `/%Q(something)/`. ([@jonas054][])
36
+ * Fix `SpacesInsideBrackets` for `Hash#[]` calls with spaces after left bracket. ([@mcls][])
37
+ * [#1210](https://github.com/bbatsov/rubocop/issues/1210): Fix false positive in `UnneededPercentQ` for `%Q(\t")`. ([@jonas054][])
38
+ * Fix false positive in `UnneededPercentQ` for heredoc strings with `%q`/`%Q`. ([@jonas054][])
39
+ * [#1214](https://github.com/bbatsov/rubocop/issues/1214): Don't destroy code in `AlignHash` autocorrect. ([@jonas054][])
40
+ * [#1219](https://github.com/bbatsov/rubocop/issues/1219): Don't report bad alignment for `end` or `}` in `BlockAlignment` if it doesn't begin its line. ([@jonas054][])
41
+ * [#1227](https://github.com/bbatsov/rubocop/issues/1227): Don't permanently change yamler as it can affect other apps. ([@jonas054][])
42
+ * [#1184](https://github.com/bbatsov/rubocop/issues/1184): Fix a false positive in `Output` cop. ([@bbatsov][])
43
+ * [#1256](https://github.com/bbatsov/rubocop/issues/1256): Ignore block-pass in `TrailingComma`. ([@tamird][])
44
+ * [#1255](https://github.com/bbatsov/rubocop/issues/1255): Compare without context in `AutocorrectUnlessChangingAST`. ([@jonas054][])
45
+ * [#1262](https://github.com/bbatsov/rubocop/issues/1262): Handle regexp and backtick literals in `VariableInterpolation`. ([@bbatsov][])
46
+
47
+ [@bbatsov]: https://github.com/bbatsov
48
+ [@jonas054]: https://github.com/jonas054
49
+ [@yujinakayama]: https://github.com/yujinakayama
50
+ [@dblock]: https://github.com/dblock
51
+ [@nevir]: https://github.com/nevir
52
+ [@daviddavis]: https://github.com/daviddavis
53
+ [@sds]: https://github.com/sds
54
+ [@fancyremarker]: https://github.com/fancyremarker
55
+ [@sinisterchipmunk]: https://github.com/sinisterchipmunk
56
+ [@vonTronje]: https://github.com/vonTronje
57
+ [@agrimm]: https://github.com/agrimm
58
+ [@pmenglund]: https://github.com/pmenglund
59
+ [@chulkilee]: https://github.com/chulkilee
60
+ [@codez]: https://github.com/codez
61
+ [@emou]: https://github.com/emou
62
+ [@skanev]: http://github.com/skanev
63
+ [@claco]: http://github.com/claco
64
+ [@rifraf]: http://github.com/rifraf
65
+ [@scottmatthewman]: https://github.com/scottmatthewman
66
+ [@ma2gedev]: http://github.com/ma2gedev
67
+ [@jeremyolliver]: https://github.com/jeremyolliver
68
+ [@hannestyden]: https://github.com/hannestyden
69
+ [@geniou]: https://github.com/geniou
70
+ [@jkogara]: https://github.com/jkogara
71
+ [@tmorris-fiksu]: https://github.com/tmorris-fiksu
72
+ [@mockdeep]: https://github.com/mockdeep
73
+ [@hiroponz]: https://github.com/hiroponz
74
+ [@tamird]: https://github.com/tamird
75
+ [@fshowalter]: https://github.com/fshowalter
76
+ [@cschramm]: https://github.com/cschramm
77
+ [@bquorning]: https://github.com/bquorning
78
+ [@bcobb]: https://github.com/bcobb
79
+ [@irrationalfab]: https://github.com/irrationalfab
80
+ [@tommeier]: https://github.com/tommeier
81
+ [@sfeldon]: https://github.com/sfeldon
82
+ [@biinari]: https://github.com/biinari
83
+ [@barunio]: https://github.com/barunio
84
+ [@molawson]: https://github.com/molawson
85
+ [@wndhydrnt]: https://github.com/wndhydrnt
86
+ [@ggilder]: https://github.com/ggilder
87
+ [@salbertson]: https://github.com/salbertson
88
+ [@camilleldn]: https://github.com/camilleldn
89
+ [@mcls]: https://github.com/mcls
90
+ [@yous]: https://github.com/yous
91
+ [@vrthra]: https://github.com/vrthra