rubocop 0.62.0 → 0.63.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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