rubocop 0.62.0 → 0.63.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +2 -2
  4. data/config/default.yml +38 -12
  5. data/lib/rubocop.rb +5 -1
  6. data/lib/rubocop/ast/builder.rb +2 -0
  7. data/lib/rubocop/ast/node/if_node.rb +29 -0
  8. data/lib/rubocop/ast/node/range_node.rb +11 -0
  9. data/lib/rubocop/ast/traversal.rb +3 -1
  10. data/lib/rubocop/config.rb +2 -0
  11. data/lib/rubocop/cop/cop.rb +1 -1
  12. data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +2 -1
  13. data/lib/rubocop/cop/lint/disjunctive_assignment_in_constructor.rb +80 -0
  14. data/lib/rubocop/cop/{style → lint}/flip_flop.rb +4 -3
  15. data/lib/rubocop/cop/lint/shadowed_exception.rb +22 -16
  16. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +11 -4
  17. data/lib/rubocop/cop/mixin/nil_methods.rb +9 -3
  18. data/lib/rubocop/cop/mixin/trailing_comma.rb +41 -6
  19. data/lib/rubocop/cop/naming/constant_name.rb +10 -1
  20. data/lib/rubocop/cop/naming/predicate_name.rb +1 -1
  21. data/lib/rubocop/cop/performance/range_include.rb +3 -0
  22. data/lib/rubocop/cop/rails/belongs_to.rb +120 -0
  23. data/lib/rubocop/cop/rails/ignored_skip_action_filter_option.rb +94 -0
  24. data/lib/rubocop/cop/rails/inverse_of.rb +4 -6
  25. data/lib/rubocop/cop/rails/link_to_blank.rb +37 -0
  26. data/lib/rubocop/cop/style/documentation_method.rb +6 -1
  27. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +2 -2
  28. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +10 -2
  29. data/lib/rubocop/cop/style/regexp_literal.rb +4 -3
  30. data/lib/rubocop/cop/style/safe_navigation.rb +10 -1
  31. data/lib/rubocop/cop/style/ternary_parentheses.rb +4 -6
  32. data/lib/rubocop/cop/style/yoda_condition.rb +58 -21
  33. data/lib/rubocop/options.rb +10 -5
  34. data/lib/rubocop/target_finder.rb +8 -30
  35. data/lib/rubocop/version.rb +1 -1
  36. metadata +7 -3
@@ -53,8 +53,13 @@ module RuboCop
53
53
 
54
54
  MSG = 'Missing method documentation comment.'.freeze
55
55
 
56
+ def_node_matcher :module_function_node?, <<-PATTERN
57
+ (send nil? :module_function ...)
58
+ PATTERN
59
+
56
60
  def on_def(node)
57
- check(node)
61
+ parent = node.parent
62
+ module_function_node?(parent) ? check(parent) : check(node)
58
63
  end
59
64
  alias on_defs on_def
60
65
 
@@ -3,10 +3,10 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Style
6
- # This cop is designed to help upgrade to Ruby 3.0. It will add the
6
+ # This cop is designed to help upgrade to after Ruby 3.0. It will add the
7
7
  # comment `# frozen_string_literal: true` to the top of files to
8
8
  # enable frozen string literals. Frozen string literals may be default
9
- # in Ruby 3.0. The comment will be added below a shebang and encoding
9
+ # after Ruby 3.0. The comment will be added below a shebang and encoding
10
10
  # comment. The frozen string literal comment is only valid in Ruby 2.3+.
11
11
  #
12
12
  # @example EnforcedStyle: when_needed (default)
@@ -245,7 +245,8 @@ module RuboCop
245
245
  def call_in_logical_operators?(node)
246
246
  node.parent &&
247
247
  (logical_operator?(node.parent) ||
248
- node.parent.descendants.any?(&method(:logical_operator?)))
248
+ node.parent.send_type? &&
249
+ node.parent.arguments.any?(&method(:logical_operator?)))
249
250
  end
250
251
 
251
252
  def call_in_optional_arguments?(node)
@@ -267,7 +268,9 @@ module RuboCop
267
268
  end
268
269
 
269
270
  def call_as_argument_or_chain?(node)
270
- node.parent && (node.parent.send_type? || node.parent.csend_type?)
271
+ node.parent &&
272
+ (node.parent.send_type? && !assigned_before?(node.parent, node) ||
273
+ node.parent.csend_type?)
271
274
  end
272
275
 
273
276
  def hash_literal_in_arguments?(node)
@@ -314,6 +317,11 @@ module RuboCop
314
317
  def regexp_slash_literal?(node)
315
318
  node.regexp_type? && node.loc.begin.source == '/'
316
319
  end
320
+
321
+ def assigned_before?(node, target)
322
+ node.assignment? &&
323
+ node.loc.operator.begin < target.loc.begin
324
+ end
317
325
  end
318
326
  end
319
327
  end
@@ -150,8 +150,9 @@ module RuboCop
150
150
  cop_config['AllowInnerSlashes']
151
151
  end
152
152
 
153
- def node_body(node)
154
- node.each_child_node(:str).map(&:source).join
153
+ def node_body(node, include_begin_nodes: false)
154
+ types = include_begin_nodes ? %i[str begin] : %i[str]
155
+ node.each_child_node(*types).map(&:source).join
155
156
  end
156
157
 
157
158
  def slash_literal?(node)
@@ -186,7 +187,7 @@ module RuboCop
186
187
  end
187
188
 
188
189
  def inner_slash_indices(node)
189
- text = node_body(node)
190
+ text = node_body(node, include_begin_nodes: true)
190
191
  pattern = inner_slash_before_correction(node)
191
192
  index = -1
192
193
  indices = []
@@ -101,6 +101,7 @@ module RuboCop
101
101
 
102
102
  checked_variable, receiver, method_chain, method = extract_parts(node)
103
103
  return unless receiver == checked_variable
104
+ return if use_var_only_in_unless_modifier?(node, checked_variable)
104
105
  # method is already a method call so this is actually checking for a
105
106
  # chain greater than 2
106
107
  return if chain_size(method_chain, method) > 1
@@ -109,6 +110,10 @@ module RuboCop
109
110
  add_offense(node)
110
111
  end
111
112
 
113
+ def use_var_only_in_unless_modifier?(node, variable)
114
+ node.if_type? && node.unless? && !method_called?(variable)
115
+ end
116
+
112
117
  def autocorrect(node)
113
118
  _check, body, = node.node_parts
114
119
  _checked_variable, matching_receiver, = extract_parts(node)
@@ -209,13 +214,17 @@ module RuboCop
209
214
  end
210
215
 
211
216
  def negated?(send_node)
212
- if send_node.parent && send_node.parent.send_type?
217
+ if method_called?(send_node)
213
218
  negated?(send_node.parent)
214
219
  else
215
220
  send_node.send_type? && send_node.method?(:!)
216
221
  end
217
222
  end
218
223
 
224
+ def method_called?(send_node)
225
+ send_node.parent && send_node.parent.send_type?
226
+ end
227
+
219
228
  def begin_range(node, method_call)
220
229
  range_between(node.loc.expression.begin_pos,
221
230
  method_call.loc.expression.begin_pos)
@@ -154,14 +154,12 @@ module RuboCop
154
154
  end
155
155
 
156
156
  def unparenthesized_method_call?(child)
157
- argument = method_call_argument(child)
158
-
159
- argument && !argument.parenthesized?
157
+ method_name(child) =~ /^[a-z]/i && !child.parenthesized?
160
158
  end
161
159
 
162
- def_node_matcher :method_call_argument, <<-PATTERN
163
- {(:defined? $(send nil? _) ...)
164
- (send {_ nil?} _ $(send nil? _) ...)}
160
+ def_node_matcher :method_name, <<-PATTERN
161
+ {($:defined? (send nil? _) ...)
162
+ (send {_ nil?} $_ _ ...)}
165
163
  PATTERN
166
164
 
167
165
  def correct_parenthesized(condition)
@@ -3,11 +3,11 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Style
6
- # This cop checks for Yoda conditions, i.e. comparison operations where
7
- # readability is reduced because the operands are not ordered the same
8
- # way as they would be ordered in spoken English.
6
+ # This cop can either enforce or forbid Yoda conditions,
7
+ # i.e. comparison operations where the order of expression is reversed.
8
+ # eg. `5 == x`
9
9
  #
10
- # @example EnforcedStyle: all_comparison_operators (default)
10
+ # @example EnforcedStyle: forbid_for_all_comparison_operators (default)
11
11
  # # bad
12
12
  # 99 == foo
13
13
  # "bar" != foo
@@ -20,7 +20,7 @@ module RuboCop
20
20
  # foo <= 42
21
21
  # bar > 10
22
22
  #
23
- # @example EnforcedStyle: equality_operators_only
23
+ # @example EnforcedStyle: forbid_for_equality_operators_only
24
24
  # # bad
25
25
  # 99 == foo
26
26
  # "bar" != foo
@@ -28,6 +28,28 @@ module RuboCop
28
28
  # # good
29
29
  # 99 >= foo
30
30
  # 3 < a && a < 5
31
+ #
32
+ # @example EnforcedStyle: require_for_all_comparison_operators
33
+ # # bad
34
+ # foo == 99
35
+ # foo == "bar"
36
+ # foo <= 42
37
+ # bar > 10
38
+ #
39
+ # # good
40
+ # 99 == foo
41
+ # "bar" != foo
42
+ # 42 >= foo
43
+ # 10 < bar
44
+ #
45
+ # @example EnforcedStyle: require_for_equality_operators_only
46
+ # # bad
47
+ # 99 >= foo
48
+ # 3 < a && a < 5
49
+ #
50
+ # # good
51
+ # 99 == foo
52
+ # "bar" != foo
31
53
  class YodaCondition < Cop
32
54
  include ConfigurableEnforcedStyle
33
55
  include RangeHelp
@@ -46,9 +68,10 @@ module RuboCop
46
68
  NONCOMMUTATIVE_OPERATORS = %i[===].freeze
47
69
 
48
70
  def on_send(node)
49
- return unless yoda_condition?(node)
71
+ return unless yoda_compatible_condition?(node)
72
+ return if equality_only? && non_equality_operator?(node)
50
73
 
51
- add_offense(node)
74
+ valid_yoda?(node) || add_offense(node)
52
75
  end
53
76
 
54
77
  def autocorrect(node)
@@ -59,17 +82,33 @@ module RuboCop
59
82
 
60
83
  private
61
84
 
62
- def yoda_condition?(node)
63
- return false unless node.comparison_method?
85
+ def enforce_yoda?
86
+ style == :require_for_all_comparison_operators ||
87
+ style == :require_for_equality_operators_only
88
+ end
64
89
 
65
- lhs, operator, rhs = *node
66
- if check_equality_only?
67
- return false if non_equality_operator?(operator)
68
- end
90
+ def equality_only?
91
+ style == :forbid_for_equality_operators_only ||
92
+ style == :require_for_equality_operators_only
93
+ end
69
94
 
70
- return false if noncommutative_operator?(operator)
95
+ def yoda_compatible_condition?(node)
96
+ node.comparison_method? &&
97
+ !noncommutative_operator?(node)
98
+ end
71
99
 
72
- lhs.literal? && !rhs.literal?
100
+ def both_literals?(node)
101
+ lhs, _operator, rhs = *node
102
+ lhs.literal? && rhs.literal?
103
+ end
104
+
105
+ def valid_yoda?(node)
106
+ lhs, _operator, rhs = *node
107
+
108
+ return true if lhs.literal? && rhs.literal? ||
109
+ !lhs.literal? && !rhs.literal?
110
+
111
+ enforce_yoda? ? lhs.literal? : rhs.literal?
73
112
  end
74
113
 
75
114
  def message(node)
@@ -91,15 +130,13 @@ module RuboCop
91
130
  REVERSE_COMPARISON.fetch(operator.to_s, operator)
92
131
  end
93
132
 
94
- def check_equality_only?
95
- style == :equality_operators_only
96
- end
97
-
98
- def non_equality_operator?(operator)
133
+ def non_equality_operator?(node)
134
+ _, operator, = *node
99
135
  !EQUALITY_OPERATORS.include?(operator)
100
136
  end
101
137
 
102
- def noncommutative_operator?(operator)
138
+ def noncommutative_operator?(node)
139
+ _, operator, = *node
103
140
  NONCOMMUTATIVE_OPERATORS.include?(operator)
104
141
  end
105
142
  end
@@ -9,6 +9,10 @@ module RuboCop
9
9
 
10
10
  # This class handles command line options.
11
11
  class Options
12
+ E_STDIN_NO_PATH = '-s/--stdin requires exactly one path, relative to the ' \
13
+ 'root of the project. RuboCop will use this path to determine which ' \
14
+ 'cops are enabled (via eg. Include/Exclude), and so that certain cops ' \
15
+ 'like Naming/FileName can be checked.'.freeze
12
16
  EXITING_OPTIONS = %i[version verbose_version show_cops].freeze
13
17
  DEFAULT_MAXIMUM_EXCLUSION_ITEMS = 15
14
18
 
@@ -24,11 +28,9 @@ module RuboCop
24
28
  @validator.validate_compatibility
25
29
 
26
30
  if @options[:stdin]
27
- # The parser has put the file name given after --stdin into
28
- # @options[:stdin]. The args array should be empty.
29
- if args.any?
30
- raise OptionArgumentError, '-s/--stdin requires exactly one path.'
31
- end
31
+ # The parser will put the file name given after --stdin into
32
+ # @options[:stdin]. If it did, then the args array should be empty.
33
+ raise OptionArgumentError, E_STDIN_NO_PATH if args.any?
32
34
 
33
35
  # We want the STDIN contents in @options[:stdin] and the file name in
34
36
  # args to simplify the rest of the processing.
@@ -157,6 +159,7 @@ module RuboCop
157
159
  option(opts, '-S', '--display-style-guide')
158
160
  option(opts, '-R', '--rails')
159
161
  option(opts, '-a', '--auto-correct')
162
+ option(opts, '--ignore-disable-comments')
160
163
 
161
164
  option(opts, '--safe')
162
165
 
@@ -373,6 +376,8 @@ module RuboCop
373
376
  force_exclusion: ['Force excluding files specified in the',
374
377
  'configuration `Exclude` even if they are',
375
378
  'explicitly passed as arguments.'],
379
+ ignore_disable_comments: ['Run cops even when they are disabled locally',
380
+ 'with a comment.'],
376
381
  ignore_parent_exclusion: ['Prevent from inheriting AllCops/Exclude from',
377
382
  'parent folders.'],
378
383
  force_default_config: ['Use default configuration even if configuration',
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'set'
4
- require 'open3'
5
4
 
6
5
  module RuboCop
7
6
  # This class finds target files to inspect by scanning the directory tree
@@ -60,13 +59,10 @@ module RuboCop
60
59
  end
61
60
  all_files = find_files(base_dir, File::FNM_DOTMATCH)
62
61
  hidden_files = Set.new(all_files - find_files(base_dir, 0))
63
-
64
- git_files = ls_git_files(base_dir)
65
-
66
62
  base_dir_config = @config_store.for(base_dir)
67
63
 
68
64
  target_files = all_files.select do |file|
69
- to_inspect?(file, git_files, hidden_files, base_dir_config)
65
+ to_inspect?(file, hidden_files, base_dir_config)
70
66
  end
71
67
 
72
68
  # Most recently modified file first.
@@ -75,6 +71,13 @@ module RuboCop
75
71
  target_files
76
72
  end
77
73
 
74
+ def to_inspect?(file, hidden_files, base_dir_config)
75
+ return false if base_dir_config.file_to_exclude?(file)
76
+ return true if !hidden_files.include?(file) && ruby_file?(file)
77
+
78
+ base_dir_config.file_to_include?(file)
79
+ end
80
+
78
81
  # Search for files recursively starting at the given base directory using
79
82
  # the given flags that determine how the match is made. Excluded files will
80
83
  # be removed later by the caller, but as an optimization find_files removes
@@ -97,31 +100,6 @@ module RuboCop
97
100
  Dir.glob(pattern, flags).select { |path| FileTest.file?(path) }
98
101
  end
99
102
 
100
- private
101
-
102
- def ls_git_files(base_dir)
103
- return if `sh -c 'command -v git'`.empty?
104
-
105
- output, _error, status = Open3.capture3(
106
- 'git', 'ls-files', '-z', base_dir,
107
- '--exclude-standard', '--others', '--cached', '--modified'
108
- )
109
-
110
- return unless status.success?
111
-
112
- output.split("\0").map { |git_file| "#{base_dir}/#{git_file}" }
113
- end
114
-
115
- def to_inspect?(file, git_files, hidden_files, base_dir_config)
116
- return false if base_dir_config.file_to_exclude?(file)
117
-
118
- if !hidden_files.include?(file) && ruby_file?(file)
119
- return git_files.nil? || git_files.include?(file)
120
- end
121
-
122
- base_dir_config.file_to_include?(file)
123
- end
124
-
125
103
  def toplevel_dirs(base_dir, flags)
126
104
  Dir.glob(File.join(base_dir, '*'), flags).select do |dir|
127
105
  File.directory?(dir) && !dir.end_with?('/.', '/..')
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  # This module holds the RuboCop version information.
5
5
  module Version
6
- STRING = '0.62.0'.freeze
6
+ STRING = '0.63.0'.freeze
7
7
 
8
8
  MSG = '%<version>s (using Parser %<parser_version>s, running on ' \
9
9
  '%<ruby_engine>s %<ruby_version>s %<ruby_platform>s)'.freeze
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.62.0
4
+ version: 0.63.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bozhidar Batsov
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: exe
12
12
  cert_chain: []
13
- date: 2019-01-01 00:00:00.000000000 Z
13
+ date: 2019-01-16 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: jaro_winkler
@@ -202,6 +202,7 @@ files:
202
202
  - lib/rubocop/ast/node/mixin/predicate_operator_node.rb
203
203
  - lib/rubocop/ast/node/or_node.rb
204
204
  - lib/rubocop/ast/node/pair_node.rb
205
+ - lib/rubocop/ast/node/range_node.rb
205
206
  - lib/rubocop/ast/node/regexp_node.rb
206
207
  - lib/rubocop/ast/node/resbody_node.rb
207
208
  - lib/rubocop/ast/node/send_node.rb
@@ -350,6 +351,7 @@ files:
350
351
  - lib/rubocop/cop/lint/circular_argument_reference.rb
351
352
  - lib/rubocop/cop/lint/debugger.rb
352
353
  - lib/rubocop/cop/lint/deprecated_class_methods.rb
354
+ - lib/rubocop/cop/lint/disjunctive_assignment_in_constructor.rb
353
355
  - lib/rubocop/cop/lint/duplicate_case_condition.rb
354
356
  - lib/rubocop/cop/lint/duplicate_methods.rb
355
357
  - lib/rubocop/cop/lint/duplicated_key.rb
@@ -362,6 +364,7 @@ files:
362
364
  - lib/rubocop/cop/lint/end_in_method.rb
363
365
  - lib/rubocop/cop/lint/ensure_return.rb
364
366
  - lib/rubocop/cop/lint/erb_new_arguments.rb
367
+ - lib/rubocop/cop/lint/flip_flop.rb
365
368
  - lib/rubocop/cop/lint/float_out_of_range.rb
366
369
  - lib/rubocop/cop/lint/format_parameter_mismatch.rb
367
370
  - lib/rubocop/cop/lint/handle_exceptions.rb
@@ -539,6 +542,7 @@ files:
539
542
  - lib/rubocop/cop/rails/application_job.rb
540
543
  - lib/rubocop/cop/rails/application_record.rb
541
544
  - lib/rubocop/cop/rails/assert_not.rb
545
+ - lib/rubocop/cop/rails/belongs_to.rb
542
546
  - lib/rubocop/cop/rails/blank.rb
543
547
  - lib/rubocop/cop/rails/bulk_change_table.rb
544
548
  - lib/rubocop/cop/rails/create_table_with_timestamps.rb
@@ -556,6 +560,7 @@ files:
556
560
  - lib/rubocop/cop/rails/has_many_or_has_one_dependent.rb
557
561
  - lib/rubocop/cop/rails/http_positional_arguments.rb
558
562
  - lib/rubocop/cop/rails/http_status.rb
563
+ - lib/rubocop/cop/rails/ignored_skip_action_filter_option.rb
559
564
  - lib/rubocop/cop/rails/inverse_of.rb
560
565
  - lib/rubocop/cop/rails/lexically_scoped_action_filter.rb
561
566
  - lib/rubocop/cop/rails/link_to_blank.rb
@@ -631,7 +636,6 @@ files:
631
636
  - lib/rubocop/cop/style/eval_with_location.rb
632
637
  - lib/rubocop/cop/style/even_odd.rb
633
638
  - lib/rubocop/cop/style/expand_path_arguments.rb
634
- - lib/rubocop/cop/style/flip_flop.rb
635
639
  - lib/rubocop/cop/style/for.rb
636
640
  - lib/rubocop/cop/style/format_string.rb
637
641
  - lib/rubocop/cop/style/format_string_token.rb