rubocop 0.45.0 → 0.46.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 (73) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +17 -0
  4. data/config/enabled.yml +29 -2
  5. data/lib/rubocop.rb +6 -1
  6. data/lib/rubocop/config.rb +0 -10
  7. data/lib/rubocop/config_loader.rb +21 -9
  8. data/lib/rubocop/cop/bundler/duplicated_gem.rb +69 -0
  9. data/lib/rubocop/cop/bundler/ordered_gems.rb +54 -0
  10. data/lib/rubocop/cop/cop.rb +1 -0
  11. data/lib/rubocop/cop/lint/debugger.rb +9 -1
  12. data/lib/rubocop/cop/lint/each_with_object_argument.rb +5 -6
  13. data/lib/rubocop/cop/lint/eval.rb +3 -7
  14. data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +6 -4
  15. data/lib/rubocop/cop/lint/unneeded_splat_expansion.rb +13 -4
  16. data/lib/rubocop/cop/lint/useless_comparison.rb +5 -9
  17. data/lib/rubocop/cop/lint/useless_setter_call.rb +1 -0
  18. data/lib/rubocop/cop/metrics/line_length.rb +16 -3
  19. data/lib/rubocop/cop/mixin/access_modifier_node.rb +9 -9
  20. data/lib/rubocop/cop/mixin/configurable_numbering.rb +14 -7
  21. data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +92 -20
  22. data/lib/rubocop/cop/performance/compare_with_block.rb +61 -0
  23. data/lib/rubocop/cop/performance/count.rb +21 -57
  24. data/lib/rubocop/cop/performance/detect.rb +15 -15
  25. data/lib/rubocop/cop/performance/flat_map.rb +23 -35
  26. data/lib/rubocop/cop/performance/sample.rb +84 -82
  27. data/lib/rubocop/cop/performance/string_replacement.rb +18 -43
  28. data/lib/rubocop/cop/rails/enum_uniqueness.rb +71 -0
  29. data/lib/rubocop/cop/rails/http_positional_arguments.rb +1 -1
  30. data/lib/rubocop/cop/rails/output.rb +8 -12
  31. data/lib/rubocop/cop/rails/read_write_attribute.rb +10 -6
  32. data/lib/rubocop/cop/rails/request_referer.rb +8 -9
  33. data/lib/rubocop/cop/rails/scope_args.rb +5 -11
  34. data/lib/rubocop/cop/style/access_modifier_indentation.rb +1 -1
  35. data/lib/rubocop/cop/style/and_or.rb +1 -1
  36. data/lib/rubocop/cop/style/array_join.rb +4 -8
  37. data/lib/rubocop/cop/style/block_comments.rb +1 -1
  38. data/lib/rubocop/cop/style/case_equality.rb +3 -3
  39. data/lib/rubocop/cop/style/character_literal.rb +2 -4
  40. data/lib/rubocop/cop/style/class_check.rb +6 -6
  41. data/lib/rubocop/cop/style/colon_method_call.rb +6 -6
  42. data/lib/rubocop/cop/style/each_with_object.rb +13 -17
  43. data/lib/rubocop/cop/style/empty_literal.rb +46 -36
  44. data/lib/rubocop/cop/style/empty_method.rb +96 -0
  45. data/lib/rubocop/cop/style/even_odd.rb +19 -50
  46. data/lib/rubocop/cop/style/hash_syntax.rb +4 -1
  47. data/lib/rubocop/cop/style/lambda.rb +8 -18
  48. data/lib/rubocop/cop/style/module_function.rb +14 -11
  49. data/lib/rubocop/cop/style/nil_comparison.rb +4 -7
  50. data/lib/rubocop/cop/style/non_nil_check.rb +18 -36
  51. data/lib/rubocop/cop/style/numeric_predicate.rb +9 -10
  52. data/lib/rubocop/cop/style/op_method.rb +7 -9
  53. data/lib/rubocop/cop/style/parallel_assignment.rb +1 -1
  54. data/lib/rubocop/cop/style/proc.rb +5 -9
  55. data/lib/rubocop/cop/style/redundant_freeze.rb +6 -7
  56. data/lib/rubocop/cop/style/send.rb +6 -3
  57. data/lib/rubocop/cop/style/space_inside_block_braces.rb +1 -1
  58. data/lib/rubocop/cop/style/special_global_vars.rb +3 -3
  59. data/lib/rubocop/cop/style/symbol_proc.rb +22 -43
  60. data/lib/rubocop/cop/style/ternary_parentheses.rb +67 -18
  61. data/lib/rubocop/cop/util.rb +1 -1
  62. data/lib/rubocop/cop/variable_force/assignment.rb +2 -0
  63. data/lib/rubocop/cop/variable_force/locatable.rb +8 -6
  64. data/lib/rubocop/cop/variable_force/reference.rb +2 -0
  65. data/lib/rubocop/formatter/base_formatter.rb +4 -8
  66. data/lib/rubocop/formatter/fuubar_style_formatter.rb +6 -0
  67. data/lib/rubocop/node_pattern.rb +7 -5
  68. data/lib/rubocop/processed_source.rb +1 -0
  69. data/lib/rubocop/rspec/cop_helper.rb +4 -0
  70. data/lib/rubocop/rspec/host_environment_simulation_helper.rb +1 -1
  71. data/lib/rubocop/version.rb +1 -1
  72. metadata +7 -3
  73. data/lib/rubocop/cop/performance/sort_with_block.rb +0 -53
@@ -18,19 +18,17 @@ module RuboCop
18
18
  'name its argument `other`.'.freeze
19
19
 
20
20
  OP_LIKE_METHODS = [:eql?, :equal?].freeze
21
-
22
21
  BLACKLISTED = [:+@, :-@, :[], :[]=, :<<, :`].freeze
23
22
 
24
- TARGET_ARGS = [s(:args, s(:arg, :other)),
25
- s(:args, s(:arg, :_other))].freeze
23
+ def_node_matcher :op_method_candidate?, <<-PATTERN
24
+ (def $_ (args $(arg [!:other !:_other])) _)
25
+ PATTERN
26
26
 
27
27
  def on_def(node)
28
- name, args, _body = *node
29
- return unless op_method?(name) &&
30
- args.children.one? &&
31
- !TARGET_ARGS.include?(args)
32
-
33
- add_offense(args.children.first, :expression, format(MSG, name))
28
+ op_method_candidate?(node) do |name, arg|
29
+ return unless op_method?(name)
30
+ add_offense(arg, :expression, format(MSG, name))
31
+ end
34
32
  end
35
33
 
36
34
  def op_method?(name)
@@ -184,7 +184,7 @@ module RuboCop
184
184
  class GenericCorrector
185
185
  include AutocorrectAlignment
186
186
 
187
- attr_reader :config, :node, :correction, :correction_range
187
+ attr_reader :config, :node
188
188
 
189
189
  def initialize(node, config, new_elements)
190
190
  @node = node
@@ -8,17 +8,13 @@ module RuboCop
8
8
  class Proc < Cop
9
9
  MSG = 'Use `proc` instead of `Proc.new`.'.freeze
10
10
 
11
- TARGET = s(:send, s(:const, nil, :Proc), :new)
11
+ def_node_matcher :proc_new?,
12
+ '(block $(send (const nil :Proc) :new) ...)'
12
13
 
13
14
  def on_block(node)
14
- # We're looking for
15
- # (block
16
- # (send
17
- # (const nil :Proc) :new)
18
- # ...)
19
- block_method, = *node
20
-
21
- add_offense(block_method, :expression) if block_method == TARGET
15
+ proc_new?(node) do |block_method|
16
+ add_offense(block_method, :expression)
17
+ end
22
18
  end
23
19
 
24
20
  def autocorrect(node)
@@ -16,14 +16,13 @@ module RuboCop
16
16
 
17
17
  MSG = 'Freezing immutable objects is pointless.'.freeze
18
18
 
19
- def on_send(node)
20
- receiver, method_name, *args = *node
21
-
22
- return unless method_name == :freeze &&
23
- args.empty? &&
24
- immutable_literal?(receiver)
19
+ def_node_matcher :freezing?, '(send $_ :freeze)'
25
20
 
26
- add_offense(node, :expression)
21
+ def on_send(node)
22
+ freezing?(node) do |receiver|
23
+ return unless immutable_literal?(receiver)
24
+ add_offense(node, :expression)
25
+ end
27
26
  end
28
27
 
29
28
  def autocorrect(node)
@@ -8,10 +8,13 @@ module RuboCop
8
8
  MSG = 'Prefer `Object#__send__` or `Object#public_send` to ' \
9
9
  '`send`.'.freeze
10
10
 
11
+ def_node_matcher :sending?, '(send _ :send $...)'
12
+
11
13
  def on_send(node)
12
- _receiver, method_name, *args = *node
13
- return unless method_name == :send && !args.empty?
14
- add_offense(node, :selector)
14
+ sending?(node) do |args|
15
+ return if args.empty?
16
+ add_offense(node, :selector)
17
+ end
15
18
  end
16
19
  end
17
20
  end
@@ -54,7 +54,7 @@ module RuboCop
54
54
  end
55
55
 
56
56
  def check_left_brace(inner, left_brace, args_delimiter)
57
- if inner =~ /^\S/
57
+ if inner =~ /\A\S/
58
58
  no_space_inside_left_brace(left_brace, args_delimiter)
59
59
  else
60
60
  space_inside_left_brace(left_brace, args_delimiter)
@@ -7,10 +7,10 @@ module RuboCop
7
7
  class SpecialGlobalVars < Cop
8
8
  include ConfigurableEnforcedStyle
9
9
 
10
- MSG_BOTH = 'Prefer `%s` from the stdlib \'English\' module, ' \
11
- 'or `%s` over `%s`.'.freeze
10
+ MSG_BOTH = 'Prefer `%s` from the stdlib \'English\' module ' \
11
+ '(don\'t forget to require it), or `%s` over `%s`.'.freeze
12
12
  MSG_ENGLISH = 'Prefer `%s` from the stdlib \'English\' module ' \
13
- 'over `%s`.'.freeze
13
+ '(don\'t forget to require it) over `%s`.'.freeze
14
14
  MSG_REGULAR = 'Prefer `%s` over `%s`.'.freeze
15
15
 
16
16
  ENGLISH_VARS = { # rubocop:disable Style/MutableConstant
@@ -13,23 +13,30 @@ module RuboCop
13
13
  # something.map(&:upcase)
14
14
  class SymbolProc < Cop
15
15
  MSG = 'Pass `&:%s` as an argument to `%s` instead of a block.'.freeze
16
+ SUPER_TYPES = [:super, :zsuper].freeze
16
17
 
17
- PROC_NODE = s(:send, s(:const, nil, :Proc), :new)
18
+ def_node_matcher :proc_node?, '(send (const nil :Proc) :new)'
19
+ def_node_matcher :symbol_proc?, <<-PATTERN
20
+ (block
21
+ ${(send ...) (super ...) zsuper}
22
+ $(args (arg _))
23
+ $(send lvar $_))
24
+ PATTERN
18
25
 
19
26
  def on_block(node)
20
- block_send_or_super, block_args, block_body = *node
21
- block_method_name = resolve_block_method_name(block_send_or_super)
22
-
23
- # TODO: Rails-specific handling that we should probably make
24
- # configurable - https://github.com/bbatsov/rubocop/issues/1485
25
- # we should ignore lambdas & procs
26
- return if block_send_or_super == PROC_NODE
27
- return if [:lambda, :proc].include?(block_method_name)
28
- return if ignored_method?(block_method_name)
29
- return unless can_shorten?(block_args, block_body)
30
-
31
- _receiver, method_name, _args = *block_body
32
- offense(node, method_name, block_method_name)
27
+ symbol_proc?(node) do |send_or_super, block_args, block_body, method|
28
+ block_method_name = resolve_block_method_name(send_or_super)
29
+
30
+ # TODO: Rails-specific handling that we should probably make
31
+ # configurable - https://github.com/bbatsov/rubocop/issues/1485
32
+ # we should ignore lambdas & procs
33
+ return if proc_node?(send_or_super)
34
+ return if [:lambda, :proc].include?(block_method_name)
35
+ return if ignored_method?(block_method_name)
36
+ return unless can_shorten?(block_args, block_body)
37
+
38
+ offense(node, method, block_method_name)
39
+ end
33
40
  end
34
41
 
35
42
  def autocorrect(node)
@@ -114,9 +121,6 @@ module RuboCop
114
121
  end
115
122
 
116
123
  def can_shorten?(block_args, block_body)
117
- return false unless shortenable_args?(block_args) &&
118
- shortenable_body?(block_body)
119
-
120
124
  argument_matches_receiver?(block_args, block_body)
121
125
  end
122
126
 
@@ -130,33 +134,8 @@ module RuboCop
130
134
  block_arg_name == receiver_name
131
135
  end
132
136
 
133
- # The block body must have a single send without arguments to an
134
- # lvar type.
135
- # E.g.: `foo { |bar| bar.baz }`
136
- def shortenable_body?(block_body)
137
- return false unless block_body && block_body.send_type?
138
-
139
- receiver, _, args = *block_body
140
-
141
- return false if args
142
-
143
- receiver && receiver.lvar_type?
144
- end
145
-
146
- # The block must have a single, shortenable argument.
147
- # E.g.: `foo { |bar| ... }`
148
- def shortenable_args?(block_args)
149
- block_args.children.one? && !non_shortenable_args?(block_args)
150
- end
151
-
152
137
  def super?(node)
153
- [:super, :zsuper].include?(node.type)
154
- end
155
-
156
- def non_shortenable_args?(block_args)
157
- # something { |&x| ... }
158
- # something { |*x| ... }
159
- [:blockarg, :restarg].include?(block_args.children.first.type)
138
+ SUPER_TYPES.include?(node.type)
160
139
  end
161
140
  end
162
141
  end
@@ -34,17 +34,32 @@ module RuboCop
34
34
  # foo = (bar?) ? a : b
35
35
  # foo = (bar.baz) ? a : b
36
36
  # foo = (bar && baz) ? a : b
37
+ #
38
+ # @example
39
+ #
40
+ # EnforcedStyle: require_parentheses_when_complex
41
+ #
42
+ # @bad
43
+ # foo = (bar?) ? a : b
44
+ # foo = (bar.baz?) ? a : b
45
+ # foo = bar && baz ? a : b
46
+ #
47
+ # @good
48
+ # foo = bar? ? a : b
49
+ # foo = bar.baz ? a : b
50
+ # foo = (bar && baz) ? a : b
37
51
  class TernaryParentheses < Cop
38
52
  include IfNode
39
53
  include SafeAssignment
40
54
  include ConfigurableEnforcedStyle
41
55
 
42
56
  MSG = '%s parentheses for ternary conditions.'.freeze
57
+ MSG_COMPLEX = '%s parentheses for ternary expressions with' \
58
+ ' complex conditions.'.freeze
43
59
 
44
60
  def on_if(node)
45
- return unless ternary?(node)
46
-
47
- add_offense(node, node.source_range, message) if offense?(node)
61
+ return unless ternary?(node) && !infinite_loop? && offense?(node)
62
+ add_offense(node, node.source_range, message(node))
48
63
  end
49
64
 
50
65
  private
@@ -52,39 +67,74 @@ module RuboCop
52
67
  def offense?(node)
53
68
  condition, = *node
54
69
 
55
- (require_parentheses? && !parenthesized?(condition) ||
56
- !require_parentheses? && parenthesized?(condition)) &&
57
- !(safe_assignment?(condition) && safe_assignment_allowed?) &&
58
- !infinite_loop?
70
+ if safe_assignment?(condition)
71
+ !safe_assignment_allowed?
72
+ else
73
+ parens = parenthesized?(condition)
74
+ case style
75
+ when :require_parentheses_when_complex
76
+ complex_condition?(condition) ? !parens : parens
77
+ else
78
+ require_parentheses? ? !parens : parens
79
+ end
80
+ end
59
81
  end
60
82
 
61
83
  def autocorrect(node)
62
84
  condition, = *node
63
85
 
86
+ return nil if parenthesized?(condition) &&
87
+ (safe_assignment?(condition) ||
88
+ unsafe_autocorrect?(condition))
89
+
64
90
  lambda do |corrector|
65
- if require_parentheses?
91
+ if parenthesized?(condition)
92
+ corrector.remove(condition.loc.begin)
93
+ corrector.remove(condition.loc.end)
94
+ else
66
95
  corrector.insert_before(condition.source_range, '(')
67
96
  corrector.insert_after(condition.source_range, ')')
68
- else
69
- unless safe_assignment?(condition) ||
70
- unsafe_autocorrect?(condition)
71
- corrector.remove(condition.loc.begin)
72
- corrector.remove(condition.loc.end)
73
- end
74
97
  end
75
98
  end
76
99
  end
77
100
 
78
- def message
79
- verb = require_parentheses? ? 'Use' : 'Omit'
101
+ # If the condition is parenthesized we recurse and check for any
102
+ # complex expressions within it.
103
+ def complex_condition?(condition)
104
+ if condition.type == :begin
105
+ condition.to_a.any? { |x| complex_condition?(x) }
106
+ else
107
+ non_complex_type?(condition) ? false : true
108
+ end
109
+ end
80
110
 
81
- format(MSG, verb)
111
+ # Anything that is not a variable, constant, or method/.method call
112
+ # will be counted as a complex expression.
113
+ def non_complex_type?(condition)
114
+ condition.variable? || condition.const_type? ||
115
+ (condition.send_type? && !operator?(condition.method_name)) ||
116
+ condition.defined_type?
117
+ end
118
+
119
+ def message(node)
120
+ if require_parentheses_when_complex?
121
+ condition, = *node
122
+ omit = parenthesized?(condition) ? 'Only use' : 'Use'
123
+ format(MSG_COMPLEX, omit)
124
+ else
125
+ verb = require_parentheses? ? 'Use' : 'Omit'
126
+ format(MSG, verb)
127
+ end
82
128
  end
83
129
 
84
130
  def require_parentheses?
85
131
  style == :require_parentheses
86
132
  end
87
133
 
134
+ def require_parentheses_when_complex?
135
+ style == :require_parentheses_when_complex
136
+ end
137
+
88
138
  def redundant_parentheses_enabled?
89
139
  @config.for_cop('RedundantParentheses')['Enabled']
90
140
  end
@@ -109,7 +159,6 @@ module RuboCop
109
159
 
110
160
  def unparenthesized_method_call?(child)
111
161
  argument = method_call_argument(child)
112
-
113
162
  argument && argument !~ /^\(/
114
163
  end
115
164
 
@@ -24,7 +24,7 @@ module RuboCop
24
24
 
25
25
  # Match literal regex characters, not including anchors, character
26
26
  # classes, alternatives, groups, repetitions, references, etc
27
- LITERAL_REGEX = /[\w\s\-,"'!#%&<>=;:`~]|\\[^AbBdDgGhHkpPRwWXsSzZS0-9]/
27
+ LITERAL_REGEX = /[\w\s\-,"'!#%&<>=;:`~]|\\[^AbBdDgGhHkpPRwWXsSzZ0-9]/
28
28
 
29
29
  module_function
30
30
 
@@ -23,6 +23,8 @@ module RuboCop
23
23
  @node = node
24
24
  @variable = variable
25
25
  @referenced = false
26
+
27
+ super
26
28
  end
27
29
 
28
30
  def name
@@ -21,6 +21,12 @@ module RuboCop
21
21
  NON_FOR_LOOP_TYPES = LOOP_TYPES - [FOR_LOOP_TYPE]
22
22
  NON_FOR_LOOP_TYPES_CHILD_INDEX = 1
23
23
 
24
+ def initialize(*)
25
+ @branch_point_node = @branch_body_node = nil
26
+
27
+ super()
28
+ end
29
+
24
30
  def node
25
31
  raise '#node must be declared!'
26
32
  end
@@ -64,9 +70,7 @@ module RuboCop
64
70
 
65
71
  # Inner if, case, rescue, or ensure node.
66
72
  def branch_point_node
67
- if instance_variable_defined?(:@branch_point_node)
68
- return @branch_point_node
69
- end
73
+ return @branch_point_node if @branch_point_node
70
74
 
71
75
  set_branch_point_and_body_nodes!
72
76
  @branch_point_node
@@ -74,9 +78,7 @@ module RuboCop
74
78
 
75
79
  # A child node of #branch_point_node this assignment belongs.
76
80
  def branch_body_node
77
- if instance_variable_defined?(:@branch_body_node)
78
- return @branch_body_node
79
- end
81
+ return @branch_body_node if @branch_body_node
80
82
 
81
83
  set_branch_point_and_body_nodes!
82
84
  @branch_body_node
@@ -24,6 +24,8 @@ module RuboCop
24
24
 
25
25
  @node = node
26
26
  @scope = scope
27
+
28
+ super
27
29
  end
28
30
 
29
31
  # There's an implicit variable reference by the zero-arity `super`:
@@ -77,8 +77,7 @@ module RuboCop
77
77
  # all target file paths to be inspected
78
78
  #
79
79
  # @return [void]
80
- def started(target_files)
81
- end
80
+ def started(target_files); end
82
81
 
83
82
  # @api public
84
83
  #
@@ -91,8 +90,7 @@ module RuboCop
91
90
  # file specific information, currently this is always empty.
92
91
  #
93
92
  # @return [void]
94
- def file_started(file, options)
95
- end
93
+ def file_started(file, options); end
96
94
 
97
95
  # @api public
98
96
  #
@@ -107,8 +105,7 @@ module RuboCop
107
105
  # @return [void]
108
106
  #
109
107
  # @see RuboCop::Cop::Offense
110
- def file_finished(file, offenses)
111
- end
108
+ def file_finished(file, offenses); end
112
109
 
113
110
  # @api public
114
111
  #
@@ -120,8 +117,7 @@ module RuboCop
120
117
  # unless RuboCop is interrupted by user.
121
118
  #
122
119
  # @return [void]
123
- def finished(inspected_files)
124
- end
120
+ def finished(inspected_files); end
125
121
  end
126
122
  end
127
123
  end