rubocop 0.37.2 → 0.38.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 (71) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -1
  3. data/assets/output.html.erb +3 -0
  4. data/config/default.yml +14 -1
  5. data/config/disabled.yml +0 -4
  6. data/lib/rubocop.rb +0 -1
  7. data/lib/rubocop/ast_node.rb +6 -0
  8. data/lib/rubocop/ast_node/traversal.rb +1 -1
  9. data/lib/rubocop/cached_data.rb +6 -2
  10. data/lib/rubocop/config_loader.rb +7 -3
  11. data/lib/rubocop/cop/cop.rb +1 -1
  12. data/lib/rubocop/cop/lint/block_alignment.rb +91 -17
  13. data/lib/rubocop/cop/lint/else_layout.rb +24 -14
  14. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +6 -12
  15. data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +16 -10
  16. data/lib/rubocop/cop/lint/nested_method_definition.rb +1 -1
  17. data/lib/rubocop/cop/lint/unneeded_disable.rb +36 -23
  18. data/lib/rubocop/cop/lint/unused_block_argument.rb +0 -1
  19. data/lib/rubocop/cop/lint/useless_access_modifier.rb +4 -4
  20. data/lib/rubocop/cop/metrics/line_length.rb +25 -18
  21. data/lib/rubocop/cop/mixin/autocorrect_alignment.rb +1 -1
  22. data/lib/rubocop/cop/mixin/code_length.rb +1 -1
  23. data/lib/rubocop/cop/mixin/if_node.rb +0 -4
  24. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +5 -1
  25. data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +6 -6
  26. data/lib/rubocop/cop/mixin/trailing_comma.rb +26 -24
  27. data/lib/rubocop/cop/mixin/unused_argument.rb +9 -1
  28. data/lib/rubocop/cop/offense.rb +16 -0
  29. data/lib/rubocop/cop/performance/casecmp.rb +15 -10
  30. data/lib/rubocop/cop/performance/count.rb +3 -2
  31. data/lib/rubocop/cop/performance/fixed_size.rb +13 -12
  32. data/lib/rubocop/cop/performance/reverse_each.rb +15 -14
  33. data/lib/rubocop/cop/rails/date.rb +13 -1
  34. data/lib/rubocop/cop/rails/output.rb +2 -1
  35. data/lib/rubocop/cop/rails/pluralization_grammar.rb +1 -1
  36. data/lib/rubocop/cop/rails/read_write_attribute.rb +1 -1
  37. data/lib/rubocop/cop/style/and_or.rb +1 -2
  38. data/lib/rubocop/cop/style/block_delimiters.rb +41 -48
  39. data/lib/rubocop/cop/style/braces_around_hash_parameters.rb +4 -2
  40. data/lib/rubocop/cop/style/class_and_module_children.rb +3 -3
  41. data/lib/rubocop/cop/style/comment_annotation.rb +8 -10
  42. data/lib/rubocop/cop/style/conditional_assignment.rb +7 -2
  43. data/lib/rubocop/cop/style/encoding.rb +15 -10
  44. data/lib/rubocop/cop/style/extra_spacing.rb +14 -12
  45. data/lib/rubocop/cop/style/file_name.rb +3 -7
  46. data/lib/rubocop/cop/style/lambda.rb +17 -6
  47. data/lib/rubocop/cop/style/method_call_parentheses.rb +1 -1
  48. data/lib/rubocop/cop/style/method_def_parentheses.rb +0 -4
  49. data/lib/rubocop/cop/style/nested_modifier.rb +7 -1
  50. data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +0 -4
  51. data/lib/rubocop/cop/style/not.rb +27 -5
  52. data/lib/rubocop/cop/style/one_line_conditional.rb +21 -0
  53. data/lib/rubocop/cop/style/redundant_parentheses.rb +9 -1
  54. data/lib/rubocop/cop/style/signal_exception.rb +28 -26
  55. data/lib/rubocop/cop/style/space_around_keyword.rb +10 -6
  56. data/lib/rubocop/cop/style/string_literals.rb +1 -0
  57. data/lib/rubocop/cop/style/unless_else.rb +24 -0
  58. data/lib/rubocop/cop/style/unneeded_interpolation.rb +26 -13
  59. data/lib/rubocop/cop/style/zero_length_predicate.rb +5 -3
  60. data/lib/rubocop/cop/team.rb +6 -1
  61. data/lib/rubocop/cop/util.rb +13 -6
  62. data/lib/rubocop/formatter/clang_style_formatter.rb +18 -14
  63. data/lib/rubocop/formatter/html_formatter.rb +9 -10
  64. data/lib/rubocop/rake_task.rb +4 -4
  65. data/lib/rubocop/remote_config.rb +4 -2
  66. data/lib/rubocop/result_cache.rb +14 -8
  67. data/lib/rubocop/runner.rb +9 -0
  68. data/lib/rubocop/version.rb +1 -1
  69. data/spec/support/cop_helper.rb +81 -0
  70. metadata +13 -7
  71. data/lib/rubocop/cop/mixin/autocorrect_unless_changing_ast.rb +0 -57
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b548479b22a3d4b42dd0cf160e59a5dac37ed348
4
- data.tar.gz: 8dffc754b643dd17217ba127b5fcaac29d9eaf7a
3
+ metadata.gz: c755e82e5751b549039b4eb7556f74a512045e00
4
+ data.tar.gz: 0c943dff109818624263c8d44e8d533208f066e0
5
5
  SHA512:
6
- metadata.gz: c6c841494e223ffe783fa455cda9de2fe53068cbf1e1f2477219b83c7f7e404289f211d0481b495991dc94d34c3c9c61cd9cba1e3214f262dc9ba4b57835da98
7
- data.tar.gz: 3a06b603d732922bee4ffd5ec8c24d9c3c4b36eb5f26cd9c0bf7cf4d85a281e88afab9dfbed907adf04f56f7cded0b0184b71531e6bfc9980b86534968465efa
6
+ metadata.gz: 64399fb16df2d1275a11f442b7904d6c036918509eccaffc2be52feea9ed1509d7f5d83c4f9b0eba7542c6d41c60d55c0a5d6ccf7a4c035569b510fcfc014345
7
+ data.tar.gz: d87cb665637072f82c9b95800d784e0457c817d7da5a4c95ac55675b1ac71447bd54074fc4018488b949d1e10394379961485583c0314d5385d6d57f6b40ae86
data/README.md CHANGED
@@ -115,7 +115,7 @@ haven't reached version 1.0 yet). To prevent an unwanted RuboCop update you
115
115
  might want to use a conservative version locking in your `Gemfile`:
116
116
 
117
117
  ```rb
118
- gem 'rubocop', '~> 0.37.2', require: false
118
+ gem 'rubocop', '~> 0.38.0', require: false
119
119
  ```
120
120
 
121
121
  ## Basic Usage
@@ -198,6 +198,7 @@ Command flag | Description
198
198
  `--show-cops` | Shows available cops and their configuration.
199
199
  `--fail-level` | Minimum [severity](#severity) for exit with error code. Full severity name or upper case initial can be given. Normally, auto-corrected offenses are ignored. Use `A` or `autocorrect` if you'd like them to trigger failure.
200
200
  `-s/--stdin` | Pipe source from STDIN. This is useful for editor integration.
201
+ `--[no-]color` | Force color output on or off.
201
202
 
202
203
  ### Cops
203
204
 
@@ -161,6 +161,9 @@
161
161
  color: #777;
162
162
  text-align: right;
163
163
  }
164
+ .extra-code {
165
+ color: #ED9C28
166
+ }
164
167
  </style>
165
168
 
166
169
  <script>
@@ -892,7 +892,7 @@ Style/TrivialAccessors:
892
892
  #
893
893
  # This way you can uncover "hidden" attributes in your code.
894
894
  ExactNameMatch: true
895
- AllowPredicates: false
895
+ AllowPredicates: true
896
896
  # Allows trivial writers that don't end in an equal sign. e.g.
897
897
  #
898
898
  # def on_exception(action)
@@ -989,6 +989,19 @@ Metrics/PerceivedComplexity:
989
989
  Lint/AssignmentInCondition:
990
990
  AllowSafeAssignment: true
991
991
 
992
+ # checks whether the end keywords are aligned properly for `do` `end` blocks.
993
+ Lint/BlockAlignment:
994
+ # The value `start_of_block` means that the `end` should be aligned with line
995
+ # where the `do` keyword appears.
996
+ # The value `start_of_line` means it should be aligned with the whole
997
+ # expression's starting line.
998
+ # The value `either` means both are allowed.
999
+ AlignWith: either
1000
+ SupportedStyles:
1001
+ - either
1002
+ - start_of_block
1003
+ - start_of_line
1004
+
992
1005
  # Align ends correctly.
993
1006
  Lint/EndAlignment:
994
1007
  # The value `keyword` means that `end` should be aligned with the matching
@@ -123,7 +123,3 @@ Style/SymbolArray:
123
123
  Description: 'Use %i or %I for arrays of symbols.'
124
124
  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#percent-i'
125
125
  Enabled: false
126
-
127
- Lint/LiteralInInterpolation:
128
- Description: 'Avoid interpolating literals in strings'
129
- AutoCorrect: false
@@ -49,7 +49,6 @@ require 'rubocop/cop/mixin/annotation_comment'
49
49
  require 'rubocop/cop/mixin/array_hash_indentation'
50
50
  require 'rubocop/cop/mixin/array_syntax'
51
51
  require 'rubocop/cop/mixin/autocorrect_alignment'
52
- require 'rubocop/cop/mixin/autocorrect_unless_changing_ast'
53
52
  require 'rubocop/cop/mixin/check_assignment'
54
53
  require 'rubocop/cop/mixin/configurable_max'
55
54
  require 'rubocop/cop/mixin/code_length' # relies on configurable_max
@@ -462,6 +462,12 @@ module RuboCop
462
462
  source_range.begin_pos == loc.selector.begin_pos
463
463
  end
464
464
 
465
+ def binary_operation?
466
+ return false unless loc.respond_to?(:selector) && loc.selector
467
+ Cop::Util.operator?(method_name) &&
468
+ source_range.begin_pos != loc.selector.begin_pos
469
+ end
470
+
465
471
  def chained?
466
472
  return false if parent.nil? || !parent.send_type?
467
473
  receiver, _method_name, *_args = *parent
@@ -143,7 +143,6 @@ module RuboCop
143
143
  end
144
144
 
145
145
  alias on_until on_while
146
- alias on_when on_while
147
146
  alias on_module on_while
148
147
  alias on_sclass on_while
149
148
 
@@ -167,6 +166,7 @@ module RuboCop
167
166
  alias on_resbody on_case
168
167
  alias on_ensure on_case
169
168
  alias on_for on_case
169
+ alias on_when on_case
170
170
  end
171
171
  end
172
172
  end
@@ -53,8 +53,12 @@ module RuboCop
53
53
  location = Parser::Source::Range.new(source_buffer,
54
54
  o['location']['begin_pos'],
55
55
  o['location']['end_pos'])
56
- Cop::Offense.new(o['severity'], location, o['message'], o['cop_name'],
57
- o['status'].to_sym)
56
+ Cop::Offense.new(o['severity'], location,
57
+ # We know that we wrote a UTF-8 encoded string to the
58
+ # cache file, so it's safe to force-encode it back to
59
+ # UTF-8 if it happens to be ASCII-8BIT.
60
+ o['message'].force_encoding('UTF-8'),
61
+ o['cop_name'], o['status'].to_sym)
58
62
  end
59
63
  end
60
64
  end
@@ -35,7 +35,10 @@ module RuboCop
35
35
  resolve_inheritance_from_gems(hash, hash.delete('inherit_gem'))
36
36
  resolve_inheritance(path, hash)
37
37
 
38
- Array(hash.delete('require')).each { |r| require(r) }
38
+ config_dir = File.dirname(path)
39
+ Array(hash.delete('require')).each do |r|
40
+ require(File.join(config_dir, r))
41
+ end
39
42
 
40
43
  hash.delete('inherit_from')
41
44
  config = Config.new(hash, path)
@@ -66,7 +69,7 @@ module RuboCop
66
69
  def base_configs(path, inherit_from)
67
70
  configs = Array(inherit_from).compact.map do |f|
68
71
  if f =~ /\A#{URI.regexp(%w(http https))}\z/
69
- f = RemoteConfig.new(f).file
72
+ f = RemoteConfig.new(f, File.dirname(path)).file
70
73
  else
71
74
  f = File.expand_path(f, File.dirname(path))
72
75
 
@@ -210,7 +213,8 @@ module RuboCop
210
213
  break if dir_pathname.to_s == @root_level
211
214
  dirs_to_search << dir_pathname.to_s
212
215
  end
213
- dirs_to_search << Dir.home
216
+ dirs_to_search << Dir.home if ENV.key? 'HOME'
217
+ dirs_to_search
214
218
  end
215
219
 
216
220
  def old_auto_config_file_warning
@@ -157,7 +157,7 @@ module RuboCop
157
157
  end
158
158
 
159
159
  def add_offense(node, loc, message = nil, severity = nil)
160
- location = loc.is_a?(Symbol) ? node.loc.send(loc) : loc
160
+ location = loc.is_a?(Symbol) ? node.loc.public_send(loc) : loc
161
161
 
162
162
  # Don't include the same location twice for one cop.
163
163
  return if @offenses.any? { |o| o.location == location }
@@ -7,13 +7,40 @@ module RuboCop
7
7
  # This cop checks whether the end keywords are aligned properly for do
8
8
  # end blocks.
9
9
  #
10
+ # Three modes are supported through the `AlignWith` configuration
11
+ # parameter:
12
+ #
13
+ # `start_of_block` : the `end` shall be aligned with the
14
+ # start of the line where the `do` appeared.
15
+ #
16
+ # `start_of_line` : the `end` shall be aligned with the
17
+ # start of the line where the expression started.
18
+ #
19
+ # `either` (which is the default) : the `end` is allowed to be in either
20
+ # location. The autofixer will default to `start_of_line`.
21
+ #
10
22
  # @example
11
23
  #
24
+ # # either
12
25
  # variable = lambda do |i|
13
26
  # i
14
27
  # end
28
+ #
29
+ # # start_of_block
30
+ # foo.bar
31
+ # .each do
32
+ # baz
33
+ # end
34
+ #
35
+ # # start_of_line
36
+ # foo.bar
37
+ # .each do
38
+ # baz
39
+ # end
15
40
  class BlockAlignment < Cop
16
- MSG = '`%s` at %d, %d is not aligned with `%s` at %d, %d%s.'.freeze
41
+ include ConfigurableEnforcedStyle
42
+
43
+ MSG = '%s is not aligned with %s%s.'.freeze
17
44
 
18
45
  def_node_matcher :block_end_align_target?, <<-PATTERN
19
46
  {assignment?
@@ -28,6 +55,10 @@ module RuboCop
28
55
  check_block_alignment(start_for_block_node(node), node)
29
56
  end
30
57
 
58
+ def parameter_name
59
+ 'AlignWith'
60
+ end
61
+
31
62
  private
32
63
 
33
64
  def start_for_block_node(block_node)
@@ -53,9 +84,30 @@ module RuboCop
53
84
  return unless begins_its_line?(end_loc)
54
85
 
55
86
  start_loc = start_node.source_range
56
- return unless start_loc.column != end_loc.column
87
+ return unless start_loc.column != end_loc.column ||
88
+ style == :start_of_block
89
+
90
+ do_source_line_column =
91
+ compute_do_source_line_column(block_node, end_loc)
92
+ return unless do_source_line_column
93
+
94
+ error_source_line_column = if style == :start_of_block
95
+ do_source_line_column
96
+ else
97
+ loc_to_source_line_column(start_loc)
98
+ end
99
+
100
+ fmt = format(
101
+ MSG,
102
+ format_source_line_column(loc_to_source_line_column(end_loc)),
103
+ format_source_line_column(error_source_line_column),
104
+ alt_start_msg(start_loc, do_source_line_column)
105
+ )
106
+ add_offense(block_node, end_loc, fmt)
107
+ end
57
108
 
58
- do_loc = block_node.loc.begin # Actually it's either do or {.
109
+ def compute_do_source_line_column(node, end_loc)
110
+ do_loc = node.loc.begin # Actually it's either do or {.
59
111
 
60
112
  # We've found that "end" is not aligned with the start node (which
61
113
  # can be a block, a variable assignment, etc). But we also allow
@@ -64,24 +116,46 @@ module RuboCop
64
116
  # blocks.
65
117
  match = /\S.*/.match(do_loc.source_line)
66
118
  indentation_of_do_line = match.begin(0)
67
- return unless end_loc.column != indentation_of_do_line
68
-
69
- add_offense(block_node,
70
- end_loc,
71
- format(MSG, end_loc.source, end_loc.line, end_loc.column,
72
- start_loc.source.lines.to_a.first.chomp,
73
- start_loc.line, start_loc.column,
74
- alt_start_msg(match, start_loc, do_loc,
75
- indentation_of_do_line)))
119
+ return unless end_loc.column != indentation_of_do_line ||
120
+ style == :start_of_line
121
+
122
+ {
123
+ source: match[0],
124
+ line: do_loc.line,
125
+ column: indentation_of_do_line
126
+ }
127
+ end
128
+
129
+ def loc_to_source_line_column(loc)
130
+ {
131
+ source: loc.source.lines.to_a.first.chomp,
132
+ line: loc.line,
133
+ column: loc.column
134
+ }
76
135
  end
77
136
 
78
- def alt_start_msg(match, start_loc, do_loc, indentation_of_do_line)
79
- if start_loc.line == do_loc.line &&
80
- start_loc.column == indentation_of_do_line
137
+ def alt_start_msg(start_loc, source_line_column)
138
+ if style != :either
139
+ ''
140
+ elsif start_loc.line == source_line_column[:line] &&
141
+ start_loc.column == source_line_column[:column]
81
142
  ''
82
143
  else
83
- " or `#{match[0]}` at #{do_loc.line}, #{indentation_of_do_line}"
144
+ ' or ' + format_source_line_column(source_line_column)
145
+ end
146
+ end
147
+
148
+ def format_source_line_column(source_line_column)
149
+ "`#{source_line_column[:source]}` at #{source_line_column[:line]}, " \
150
+ "#{source_line_column[:column]}"
151
+ end
152
+
153
+ def compute_start_col(ancestor_node, node)
154
+ if style == :start_of_block
155
+ do_loc = node.loc.begin
156
+ return do_loc.source_line =~ /\S/
84
157
  end
158
+ (ancestor_node || node).source_range.column
85
159
  end
86
160
 
87
161
  def autocorrect(node)
@@ -89,9 +163,9 @@ module RuboCop
89
163
  source = node.source_range.source_buffer
90
164
 
91
165
  lambda do |corrector|
92
- start_col = (ancestor_node || node).source_range.column
93
166
  starting_position_of_block_end = node.loc.end.begin_pos
94
167
  end_col = node.loc.end.column
168
+ start_col = compute_start_col(ancestor_node, node)
95
169
 
96
170
  if end_col < start_col
97
171
  delta = start_col - end_col
@@ -29,24 +29,34 @@ module RuboCop
29
29
 
30
30
  def check(node)
31
31
  return unless node
32
+ return check_else(node) if else?(node)
32
33
 
33
- if node.loc.respond_to?(:else) &&
34
- node.loc.else &&
35
- node.loc.else.is?('else')
36
- _cond, _if_branch, else_branch = *node
34
+ check_if(node) if if?(node)
35
+ end
36
+
37
+ def check_else(node)
38
+ _cond, _if_branch, else_branch = *node
39
+ return unless else_branch && else_branch.type == :begin
37
40
 
38
- return unless else_branch && else_branch.type == :begin
41
+ first_else_expr = else_branch.children.first
42
+ return unless first_else_expr.source_range.line == node.loc.else.line
43
+
44
+ add_offense(first_else_expr, :expression, message)
45
+ end
39
46
 
40
- first_else_expr = else_branch.children.first
47
+ def check_if(node)
48
+ _cond, _if_branch, else_branch = *node
49
+ check(else_branch)
50
+ end
51
+
52
+ def if?(node)
53
+ node.loc.respond_to?(:keyword) &&
54
+ %w(if elsif).include?(node.loc.keyword.source)
55
+ end
41
56
 
42
- if first_else_expr.source_range.line == node.loc.else.line
43
- add_offense(first_else_expr, :expression, message)
44
- end
45
- elsif node.loc.respond_to?(:keyword) &&
46
- %w(if elsif).include?(node.loc.keyword.source)
47
- _cond, _if_branch, else_branch = *node
48
- check(else_branch)
49
- end
57
+ def else?(node)
58
+ node.loc.respond_to?(:else) && node.loc.else &&
59
+ node.loc.else.is?('else')
50
60
  end
51
61
 
52
62
  def message
@@ -34,20 +34,14 @@ module RuboCop
34
34
 
35
35
  def offending_node?(node)
36
36
  return false unless called_on_string?(node)
37
+ return false unless sprintf?(node) || format?(node) || percent?(node)
38
+ return false if named_mode?(node) || node_with_splat_args?(node)
37
39
 
38
- if sprintf?(node) || format?(node) || percent?(node)
39
- if named_mode?(node) || node_with_splat_args?(node)
40
- false
41
- else
42
- num_of_format_args, num_of_expected_fields = count_matches(node)
40
+ num_of_format_args, num_of_expected_fields = count_matches(node)
43
41
 
44
- num_of_format_args != :unknown &&
45
- num_of_expected_fields != :unknown &&
46
- num_of_expected_fields != num_of_format_args
47
- end
48
- else
49
- false
50
- end
42
+ num_of_format_args != :unknown &&
43
+ num_of_expected_fields != :unknown &&
44
+ num_of_expected_fields != num_of_format_args
51
45
  end
52
46
 
53
47
  def called_on_string?(node)
@@ -27,16 +27,7 @@ module RuboCop
27
27
  'arguments, separate them with a comma.'.freeze
28
28
 
29
29
  def on_dstr(node)
30
- node.children.each_cons(2) do |child1, child2|
31
- # `'abc' 'def'` -> (dstr (str "abc") (str "def"))
32
- next unless string_literal?(child1) && string_literal?(child2)
33
- next unless child1.loc.last_line == child2.loc.line
34
-
35
- # Make sure we don't flag a string literal which simply has
36
- # embedded newlines
37
- # `"abc\ndef"` also -> (dstr (str "abc") (str "def"))
38
- next unless child1.source[-1] == ending_delimiter(child1)
39
-
30
+ each_bad_cons(node) do |child1, child2|
40
31
  range = child1.source_range.join(child2.source_range)
41
32
  message = format(MSG, display_str(child1), display_str(child2))
42
33
  if node.parent && node.parent.array_type?
@@ -50,6 +41,21 @@ module RuboCop
50
41
 
51
42
  private
52
43
 
44
+ def each_bad_cons(node)
45
+ node.children.each_cons(2) do |child1, child2|
46
+ # `'abc' 'def'` -> (dstr (str "abc") (str "def"))
47
+ next unless string_literal?(child1) && string_literal?(child2)
48
+ next unless child1.loc.last_line == child2.loc.line
49
+
50
+ # Make sure we don't flag a string literal which simply has
51
+ # embedded newlines
52
+ # `"abc\ndef"` also -> (dstr (str "abc") (str "def"))
53
+ next unless child1.source[-1] == ending_delimiter(child1)
54
+
55
+ yield child1, child2
56
+ end
57
+ end
58
+
53
59
  def ending_delimiter(str)
54
60
  # implicit string concatenation does not work with %{}, etc.
55
61
  if str.source[0] == "'"
@@ -27,7 +27,7 @@ module RuboCop
27
27
  PATTERN
28
28
 
29
29
  def_node_matcher :class_or_module_new_call?, <<-PATTERN
30
- (block (send (const nil {:Class :Module}) :new) ...)
30
+ (block (send (const nil {:Class :Module}) :new ...) ...)
31
31
  PATTERN
32
32
 
33
33
  def on_method_def(node, _method_name, _args, _body)