rubocop 0.39.0 → 0.40.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 (89) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +11 -1
  3. data/config/default.yml +65 -2
  4. data/config/disabled.yml +0 -28
  5. data/config/enabled.yml +40 -0
  6. data/lib/rubocop.rb +3 -0
  7. data/lib/rubocop/ast_node.rb +28 -13
  8. data/lib/rubocop/cached_data.rb +15 -2
  9. data/lib/rubocop/cli.rb +24 -8
  10. data/lib/rubocop/config.rb +3 -3
  11. data/lib/rubocop/config_loader.rb +0 -7
  12. data/lib/rubocop/cop/cop.rb +2 -2
  13. data/lib/rubocop/cop/lint/condition_position.rb +3 -1
  14. data/lib/rubocop/cop/lint/else_layout.rb +3 -2
  15. data/lib/rubocop/cop/lint/end_alignment.rb +2 -2
  16. data/lib/rubocop/cop/lint/nested_method_definition.rb +15 -9
  17. data/lib/rubocop/cop/lint/require_parentheses.rb +1 -1
  18. data/lib/rubocop/cop/lint/unused_block_argument.rb +2 -0
  19. data/lib/rubocop/cop/lint/useless_access_modifier.rb +86 -20
  20. data/lib/rubocop/cop/lint/useless_array_splat.rb +56 -0
  21. data/lib/rubocop/cop/metrics/method_length.rb +1 -1
  22. data/lib/rubocop/cop/mixin/configurable_enforced_style.rb +11 -25
  23. data/lib/rubocop/cop/mixin/if_node.rb +4 -0
  24. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +14 -12
  25. data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +75 -9
  26. data/lib/rubocop/cop/mixin/on_normal_if_unless.rb +1 -1
  27. data/lib/rubocop/cop/mixin/space_after_punctuation.rb +1 -2
  28. data/lib/rubocop/cop/mixin/trailing_comma.rb +15 -5
  29. data/lib/rubocop/cop/performance/case_when_splat.rb +71 -44
  30. data/lib/rubocop/cop/performance/detect.rb +28 -18
  31. data/lib/rubocop/cop/performance/end_with.rb +1 -1
  32. data/lib/rubocop/cop/performance/redundant_merge.rb +29 -11
  33. data/lib/rubocop/cop/performance/start_with.rb +1 -1
  34. data/lib/rubocop/cop/performance/string_replacement.rb +39 -20
  35. data/lib/rubocop/cop/rails/action_filter.rb +1 -2
  36. data/lib/rubocop/cop/rails/date.rb +2 -5
  37. data/lib/rubocop/cop/rails/time_zone.rb +3 -6
  38. data/lib/rubocop/cop/rails/uniq_before_pluck.rb +57 -0
  39. data/lib/rubocop/cop/style/alias.rb +10 -3
  40. data/lib/rubocop/cop/style/align_parameters.rb +8 -2
  41. data/lib/rubocop/cop/style/and_or.rb +29 -21
  42. data/lib/rubocop/cop/style/class_and_module_children.rb +1 -1
  43. data/lib/rubocop/cop/style/collection_methods.rb +1 -2
  44. data/lib/rubocop/cop/style/comment_indentation.rb +1 -1
  45. data/lib/rubocop/cop/style/conditional_assignment.rb +13 -7
  46. data/lib/rubocop/cop/style/empty_case_condition.rb +96 -0
  47. data/lib/rubocop/cop/style/encoding.rb +9 -5
  48. data/lib/rubocop/cop/style/extra_spacing.rb +22 -7
  49. data/lib/rubocop/cop/style/file_name.rb +7 -2
  50. data/lib/rubocop/cop/style/guard_clause.rb +18 -10
  51. data/lib/rubocop/cop/style/if_inside_else.rb +1 -1
  52. data/lib/rubocop/cop/style/if_unless_modifier.rb +2 -1
  53. data/lib/rubocop/cop/style/indentation_width.rb +7 -4
  54. data/lib/rubocop/cop/style/lambda.rb +98 -30
  55. data/lib/rubocop/cop/style/line_end_concatenation.rb +5 -0
  56. data/lib/rubocop/cop/style/multiline_array_brace_layout.rb +34 -9
  57. data/lib/rubocop/cop/style/multiline_assignment_layout.rb +2 -1
  58. data/lib/rubocop/cop/style/multiline_hash_brace_layout.rb +42 -17
  59. data/lib/rubocop/cop/style/multiline_method_call_brace_layout.rb +39 -14
  60. data/lib/rubocop/cop/style/multiline_method_definition_brace_layout.rb +36 -15
  61. data/lib/rubocop/cop/style/multiline_ternary_operator.rb +8 -6
  62. data/lib/rubocop/cop/style/negated_while.rb +2 -1
  63. data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +15 -0
  64. data/lib/rubocop/cop/style/nested_ternary_operator.rb +5 -8
  65. data/lib/rubocop/cop/style/next.rb +1 -1
  66. data/lib/rubocop/cop/style/not.rb +5 -2
  67. data/lib/rubocop/cop/style/parentheses_around_condition.rb +2 -2
  68. data/lib/rubocop/cop/style/raise_args.rb +70 -7
  69. data/lib/rubocop/cop/style/redundant_exception.rb +34 -20
  70. data/lib/rubocop/cop/style/redundant_parentheses.rb +27 -1
  71. data/lib/rubocop/cop/style/space_after_colon.rb +14 -10
  72. data/lib/rubocop/cop/style/space_after_comma.rb +5 -0
  73. data/lib/rubocop/cop/style/space_after_not.rb +3 -4
  74. data/lib/rubocop/cop/style/space_after_semicolon.rb +5 -0
  75. data/lib/rubocop/cop/style/space_around_operators.rb +2 -1
  76. data/lib/rubocop/cop/style/special_global_vars.rb +4 -2
  77. data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +1 -1
  78. data/lib/rubocop/cop/style/string_methods.rb +1 -2
  79. data/lib/rubocop/cop/style/symbol_proc.rb +7 -1
  80. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +25 -0
  81. data/lib/rubocop/cop/style/word_array.rb +50 -22
  82. data/lib/rubocop/cop/util.rb +0 -4
  83. data/lib/rubocop/formatter/clang_style_formatter.rb +38 -22
  84. data/lib/rubocop/options.rb +45 -10
  85. data/lib/rubocop/path_util.rb +2 -34
  86. data/lib/rubocop/result_cache.rb +10 -4
  87. data/lib/rubocop/runner.rb +5 -3
  88. data/lib/rubocop/version.rb +1 -1
  89. metadata +7 -4
@@ -17,19 +17,10 @@ module RuboCop
17
17
  QUESTION_MARK_SIZE = '?'.size
18
18
 
19
19
  def on_array(node)
20
- array_elems = node.children
21
-
22
20
  if bracketed_array_of?(:str, node)
23
- return if complex_content?(array_elems) ||
24
- comments_in_array?(node)
25
- style_detected(:brackets, array_elems.size)
26
-
27
- if style == :percent && array_elems.size >= min_size
28
- add_offense(node, :expression, PERCENT_MSG)
29
- end
30
- elsif node.loc.begin && node.loc.begin.source =~ /\A%[wW]/
31
- style_detected(:percent, array_elems.size)
32
- add_offense(node, :expression, ARRAY_MSG) if style == :brackets
21
+ check_bracketed(node)
22
+ elsif percent_syntax?(node)
23
+ check_percent(node)
33
24
  end
34
25
  end
35
26
 
@@ -52,6 +43,29 @@ module RuboCop
52
43
 
53
44
  private
54
45
 
46
+ def check_bracketed(node)
47
+ array_elems = node.children
48
+
49
+ return if complex_content?(array_elems) ||
50
+ comments_in_array?(node)
51
+ style_detected(:brackets, array_elems.size)
52
+
53
+ if style == :percent && array_elems.size >= min_size
54
+ add_offense(node, :expression, PERCENT_MSG)
55
+ end
56
+ end
57
+
58
+ def check_percent(node)
59
+ array_elems = node.children
60
+
61
+ style_detected(:percent, array_elems.size)
62
+ add_offense(node, :expression, ARRAY_MSG) if style == :brackets
63
+ end
64
+
65
+ def percent_syntax?(node)
66
+ node.loc.begin && node.loc.begin.source =~ /\A%[wW]/
67
+ end
68
+
55
69
  def comments_in_array?(node)
56
70
  comments = processed_source.comments
57
71
  array_range = node.source_range.to_a
@@ -101,26 +115,40 @@ module RuboCop
101
115
  cfg = config_to_allow_offenses
102
116
  return if cfg['Enabled'] == false
103
117
 
104
- @largest_brackets ||= -Float::INFINITY
105
- @smallest_percent ||= Float::INFINITY
106
-
107
- if style == :percent
108
- @smallest_percent = ary_size if ary_size < @smallest_percent
109
- elsif ary_size > @largest_brackets
110
- @largest_brackets = ary_size
111
- end
118
+ largest_brackets = largest_brackets_size(style, ary_size)
119
+ smallest_percent = smallest_percent_size(style, ary_size)
112
120
 
113
121
  if cfg['EnforcedStyle'] == style.to_s
114
122
  # do nothing
115
123
  elsif cfg['EnforcedStyle'].nil?
116
124
  cfg['EnforcedStyle'] = style.to_s
117
- elsif @smallest_percent <= @largest_brackets
125
+ elsif smallest_percent <= largest_brackets
118
126
  self.config_to_allow_offenses = { 'Enabled' => false }
119
127
  else
120
128
  cfg['EnforcedStyle'] = 'percent'
121
- cfg['MinSize'] = @largest_brackets + 1
129
+ cfg['MinSize'] = largest_brackets + 1
122
130
  end
123
131
  end
132
+
133
+ def largest_brackets_size(style, ary_size)
134
+ @largest_brackets ||= -Float::INFINITY
135
+
136
+ if style == :brackets && ary_size > @largest_brackets
137
+ @largest_brackets = ary_size
138
+ end
139
+
140
+ @largest_brackets
141
+ end
142
+
143
+ def smallest_percent_size(style, ary_size)
144
+ @smallest_percent ||= Float::INFINITY
145
+
146
+ if style == :percent && ary_size < @smallest_percent
147
+ @smallest_percent = ary_size
148
+ end
149
+
150
+ @smallest_percent
151
+ end
124
152
  end
125
153
  end
126
154
  end
@@ -46,10 +46,6 @@ module RuboCop
46
46
  OPERATOR_METHODS.include?(symbol)
47
47
  end
48
48
 
49
- def ternary_op?(node)
50
- node.loc.respond_to?(:question)
51
- end
52
-
53
49
  def strip_quotes(str)
54
50
  if str[0] == '"' || str[0] == "'"
55
51
  str[0] = ''
@@ -10,29 +10,45 @@ module RuboCop
10
10
  ELLIPSES = Rainbow('...').yellow.freeze
11
11
 
12
12
  def report_file(file, offenses)
13
- offenses.each do |o|
14
- output.printf("%s:%d:%d: %s: %s\n",
15
- cyan(smart_path(file)), o.line, o.real_column,
16
- colored_severity_code(o), message(o))
17
-
18
- # rubocop:disable Lint/HandleExceptions
19
- begin
20
- location = o.location
21
- source_line = location.source_line
22
- next if source_line.blank?
23
-
24
- if location.first_line == location.last_line
25
- output.puts(source_line)
26
- else
27
- output.puts("#{source_line} #{ELLIPSES}")
28
- end
29
- output.puts("#{' ' * o.highlighted_area.begin_pos}" \
30
- "#{'^' * o.highlighted_area.size}")
31
- rescue IndexError
32
- # range is not on a valid line; perhaps the source file is empty
33
- end
34
- # rubocop:enable Lint/HandleExceptions
13
+ offenses.each { |offense| report_offense(file, offense) }
14
+ end
15
+
16
+ private
17
+
18
+ def report_offense(file, offense)
19
+ output.printf("%s:%d:%d: %s: %s\n",
20
+ cyan(smart_path(file)), offense.line, offense.real_column,
21
+ colored_severity_code(offense), message(offense))
22
+
23
+ # rubocop:disable Lint/HandleExceptions
24
+ begin
25
+ return unless valid_line?(offense)
26
+
27
+ report_line(offense.location)
28
+ report_highlighted_area(offense.highlighted_area)
29
+ rescue IndexError
30
+ # range is not on a valid line; perhaps the source file is empty
35
31
  end
32
+ # rubocop:enable Lint/HandleExceptions
33
+ end
34
+
35
+ def valid_line?(offense)
36
+ !offense.location.source_line.blank?
37
+ end
38
+
39
+ def report_line(location)
40
+ source_line = location.source_line
41
+
42
+ if location.first_line == location.last_line
43
+ output.puts(source_line)
44
+ else
45
+ output.puts("#{source_line} #{ELLIPSES}")
46
+ end
47
+ end
48
+
49
+ def report_highlighted_area(highlighted_area)
50
+ output.puts("#{' ' * highlighted_area.begin_pos}" \
51
+ "#{'^' * highlighted_area.size}")
36
52
  end
37
53
  end
38
54
  end
@@ -2,6 +2,7 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require 'optparse'
5
+ require 'shellwords'
5
6
 
6
7
  module RuboCop
7
8
  # This class handles command line options.
@@ -14,7 +15,8 @@ module RuboCop
14
15
  @validator = OptionsValidator.new(@options)
15
16
  end
16
17
 
17
- def parse(args)
18
+ def parse(command_line_args)
19
+ args = args_from_file.concat(args_from_env).concat(command_line_args)
18
20
  define_options(args).parse!(args)
19
21
  # The --no-color CLI option sets `color: false` so we don't want the
20
22
  # `no_color` key, which is created automatically.
@@ -31,6 +33,18 @@ module RuboCop
31
33
 
32
34
  private
33
35
 
36
+ def args_from_file
37
+ if File.exist?('.rubocop')
38
+ IO.readlines('.rubocop').map(&:strip)
39
+ else
40
+ []
41
+ end
42
+ end
43
+
44
+ def args_from_env
45
+ Shellwords.split(ENV.fetch('RUBOCOP_OPTS', ''))
46
+ end
47
+
34
48
  def define_options(args)
35
49
  OptionParser.new do |opts|
36
50
  opts.banner = 'Usage: rubocop [options] [file1, file2, ...]'
@@ -179,23 +193,44 @@ module RuboCop
179
193
  end
180
194
 
181
195
  def validate_compatibility
182
- if @options.key?(:only) &&
183
- (@options[:only] & %w(Lint/UnneededDisable UnneededDisable)).any?
196
+ if only_includes_unneeded_disable?
184
197
  raise ArgumentError, 'Lint/UnneededDisable can not be used with --only.'
185
198
  end
186
- if @options.key?(:except) &&
187
- (@options[:except] & %w(Lint/Syntax Syntax)).any?
199
+ if except_syntax?
188
200
  raise ArgumentError, 'Syntax checking can not be turned off.'
189
201
  end
190
- if @options.key?(:cache) && !%w(true false).include?(@options[:cache])
202
+ unless boolean_or_empty_cache?
191
203
  raise ArgumentError, '-C/--cache argument must be true or false'
192
204
  end
193
- if @options.key?(:no_offense_counts) && !@options.key?(:auto_gen_config)
205
+ if no_offense_counts_without_auto_gen_config?
194
206
  raise ArgumentError, '--no-offense-counts can only be used together ' \
195
- 'with --auto-gen-config.'
207
+ 'with --auto-gen-config.'
196
208
  end
197
- return if (incompat = @options.keys & Options::EXITING_OPTIONS).size <= 1
198
- raise ArgumentError, "Incompatible cli options: #{incompat.inspect}"
209
+ return if incompatible_options.size <= 1
210
+ raise ArgumentError, 'Incompatible cli options: ' \
211
+ "#{incompatible_options.inspect}"
212
+ end
213
+
214
+ def only_includes_unneeded_disable?
215
+ @options.key?(:only) &&
216
+ (@options[:only] & %w(Lint/UnneededDisable UnneededDisable)).any?
217
+ end
218
+
219
+ def except_syntax?
220
+ @options.key?(:except) &&
221
+ (@options[:except] & %w(Lint/Syntax Syntax)).any?
222
+ end
223
+
224
+ def boolean_or_empty_cache?
225
+ !@options.key?(:cache) || %w(true false).include?(@options[:cache])
226
+ end
227
+
228
+ def no_offense_counts_without_auto_gen_config?
229
+ @options.key?(:no_offense_counts) && !@options.key?(:auto_gen_config)
230
+ end
231
+
232
+ def incompatible_options
233
+ @incompatible_options ||= @options.keys & Options::EXITING_OPTIONS
199
234
  end
200
235
 
201
236
  def validate_exclude_limit_option(args)
@@ -15,47 +15,15 @@ module RuboCop
15
15
  path_name.relative_path_from(Pathname.new(base_dir)).to_s
16
16
  end
17
17
 
18
- # TODO: The old way of matching patterns is flawed, so a new one has been
19
- # introduced. We keep supporting the old way for a while and issue
20
- # deprecation warnings when a pattern is used that produced a match with
21
- # the old way but doesn't match with the new.
22
- def match_path?(pattern, path, config_path)
18
+ def match_path?(pattern, path)
23
19
  case pattern
24
20
  when String
25
- basename = File.basename(path)
26
- old_match = basename == pattern || File.fnmatch?(pattern, path)
27
- new_match = File.fnmatch?(pattern, path, File::FNM_PATHNAME)
28
- if old_match && !new_match
29
- # Patterns like dir/**/* will produce an old match for files
30
- # beginning with dot, but not a new match. That's a special case,
31
- # though. Not what we want to handle here. And this is a match that
32
- # we overrule. Only patterns like dir/**/.* can be used to match dot
33
- # files. Hidden directories (starting with a dot) will also produce
34
- # an old match, just like hidden files.
35
- return false if path.split(File::SEPARATOR).any? { |s| hidden?(s) }
36
-
37
- issue_deprecation_warning(basename, pattern, config_path)
38
- end
39
- old_match || new_match
21
+ File.fnmatch?(pattern, path, File::FNM_PATHNAME)
40
22
  when Regexp
41
23
  path =~ pattern
42
24
  end
43
25
  end
44
26
 
45
- def issue_deprecation_warning(basename, pattern, config_path)
46
- instruction = if basename == pattern
47
- ". Change to '**/#{pattern}'."
48
- elsif pattern.end_with?('**')
49
- ". Change to '#{pattern}/*'."
50
- end
51
- warn("Warning: Deprecated pattern style '#{pattern}' in " \
52
- "#{config_path}#{instruction}")
53
- end
54
-
55
- def hidden?(path_component)
56
- path_component =~ /^\.[^.]/
57
- end
58
-
59
27
  # Returns true for an absolute Unix or Windows path.
60
28
  def absolute?(path)
61
29
  path =~ %r{\A([A-Z]:)?/}
@@ -128,10 +128,16 @@ module RuboCop
128
128
  begin
129
129
  lib_root = File.join(File.dirname(__FILE__), '..')
130
130
  bin_root = File.join(lib_root, '..', 'bin')
131
- source = Find.find(lib_root, bin_root).sort.map do |path|
132
- IO.read(path) if File.file?(path)
133
- end
134
- Digest::MD5.hexdigest(source.join)
131
+
132
+ # These are all the files we have `require`d plus everything in the
133
+ # bin directory. A change to any of them could affect the cop output
134
+ # so we include them in the cache hash.
135
+ source_files = $LOADED_FEATURES + Find.find(bin_root).to_a
136
+ sources = source_files
137
+ .select { |path| File.file?(path) }
138
+ .sort
139
+ .map { |path| IO.read(path) }
140
+ Digest::MD5.hexdigest(sources.join)
135
141
  end
136
142
  end
137
143
 
@@ -102,10 +102,12 @@ module RuboCop
102
102
  # given, because these options override configuration.
103
103
  (@options[:except] || []).empty? && (@options[:only] || []).empty?
104
104
  config = @config_store.for(file)
105
- if config['Lint/UnneededDisable']['Enabled']
105
+ if config.cop_enabled?(Cop::Lint::UnneededDisable)
106
106
  cop = Cop::Lint::UnneededDisable.new(config, @options)
107
- cop.check(offenses, source.disabled_line_ranges, source.comments)
108
- offenses += cop.offenses
107
+ if cop.relevant_file?(file)
108
+ cop.check(offenses, source.disabled_line_ranges, source.comments)
109
+ offenses += cop.offenses
110
+ end
109
111
  end
110
112
  end
111
113
 
@@ -4,7 +4,7 @@
4
4
  module RuboCop
5
5
  # This module holds the RuboCop version information.
6
6
  module Version
7
- STRING = '0.39.0'.freeze
7
+ STRING = '0.40.0'.freeze
8
8
 
9
9
  MSG = '%s (using Parser %s, running on %s %s %s)'.freeze
10
10
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubocop
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.39.0
4
+ version: 0.40.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bozhidar Batsov
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2016-03-27 00:00:00.000000000 Z
13
+ date: 2016-05-09 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rainbow
@@ -38,7 +38,7 @@ dependencies:
38
38
  requirements:
39
39
  - - ">="
40
40
  - !ruby/object:Gem::Version
41
- version: 2.3.0.7
41
+ version: 2.3.1.0
42
42
  - - "<"
43
43
  - !ruby/object:Gem::Version
44
44
  version: '3.0'
@@ -48,7 +48,7 @@ dependencies:
48
48
  requirements:
49
49
  - - ">="
50
50
  - !ruby/object:Gem::Version
51
- version: 2.3.0.7
51
+ version: 2.3.1.0
52
52
  - - "<"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '3.0'
@@ -195,6 +195,7 @@ files:
195
195
  - lib/rubocop/cop/lint/unused_block_argument.rb
196
196
  - lib/rubocop/cop/lint/unused_method_argument.rb
197
197
  - lib/rubocop/cop/lint/useless_access_modifier.rb
198
+ - lib/rubocop/cop/lint/useless_array_splat.rb
198
199
  - lib/rubocop/cop/lint/useless_assignment.rb
199
200
  - lib/rubocop/cop/lint/useless_comparison.rb
200
201
  - lib/rubocop/cop/lint/useless_else_without_rescue.rb
@@ -281,6 +282,7 @@ files:
281
282
  - lib/rubocop/cop/rails/read_write_attribute.rb
282
283
  - lib/rubocop/cop/rails/scope_args.rb
283
284
  - lib/rubocop/cop/rails/time_zone.rb
285
+ - lib/rubocop/cop/rails/uniq_before_pluck.rb
284
286
  - lib/rubocop/cop/rails/validation.rb
285
287
  - lib/rubocop/cop/severity.rb
286
288
  - lib/rubocop/cop/style/access_modifier_indentation.rb
@@ -325,6 +327,7 @@ files:
325
327
  - lib/rubocop/cop/style/double_negation.rb
326
328
  - lib/rubocop/cop/style/each_with_object.rb
327
329
  - lib/rubocop/cop/style/else_alignment.rb
330
+ - lib/rubocop/cop/style/empty_case_condition.rb
328
331
  - lib/rubocop/cop/style/empty_else.rb
329
332
  - lib/rubocop/cop/style/empty_line_between_defs.rb
330
333
  - lib/rubocop/cop/style/empty_lines.rb