rubocop-performance 1.21.1 → 1.23.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dd286ebd5cb0d982f759a355a86281898577db559004bef9bfb53b8493a32934
4
- data.tar.gz: f3e101a14918c3efa6dc657841471b22afec47d54ce70442567d54ffc3ee8ed5
3
+ metadata.gz: 332ca643753a81ff66c4a6050117f7a479bd3aaa3f186c361a596d06b16aa9b5
4
+ data.tar.gz: 2fb149f85f986d9d0302e6fbe4c7389f312bb93a15a93cec49ffd74495853c78
5
5
  SHA512:
6
- metadata.gz: 1d6df8e36cbb224d892f14e7fb1eeccf34c887c9fd6e9ad302889ab71b64e48db3c3167291f210ad7e69a23f5e4720ae23ee767c4a569701d09e8fa771ede28c
7
- data.tar.gz: 428da3a79195bcf8c715a1962c5bea38a08ee2973c0450b78fc24ceeb376a4f984b3d4f91efba93c799d28986dda22f711e90937738007abbd41b470a484a887
6
+ metadata.gz: e03b8e178f4cde75ef5d82aa7483da512f2816afd82c97b414a4bfcd7afacf589ebb033d6bed40d0968217ec0ff24cb69e2a6c4f28a52ecbdb31cef5599e5386
7
+ data.tar.gz: 410a72e5e85fe6cdc8002b51c8b185dc4d2a1dea5f3a5889c146364c2a20b5b50256c2a90fef59604137dd75d83f20c17ec65991eac6b8dab15e046184e1f006
data/LICENSE.txt CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2012-23 Bozhidar Batsov
1
+ Copyright (c) 2012-25 Bozhidar Batsov
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/config/default.yml CHANGED
@@ -32,8 +32,11 @@ Performance/BindCall:
32
32
 
33
33
  Performance/BlockGivenWithExplicitBlock:
34
34
  Description: 'Check block argument explicitly instead of using `block_given?`.'
35
- Enabled: pending
35
+ # This cop was created due to a mistake in microbenchmark.
36
+ # https://github.com/rubocop/rubocop-performance/issues/385
37
+ Enabled: false
36
38
  VersionAdded: '1.9'
39
+ VersionChanged: '1.22'
37
40
 
38
41
  Performance/Caller:
39
42
  Description: >-
@@ -323,6 +326,12 @@ Performance/StartWith:
323
326
  VersionAdded: '0.36'
324
327
  VersionChanged: '1.10'
325
328
 
329
+ Performance/StringBytesize:
330
+ Description: "Use `String#bytesize` instead of calculating the size of the bytes array."
331
+ Safe: false
332
+ Enabled: 'pending'
333
+ VersionAdded: '1.23'
334
+
326
335
  Performance/StringIdentifierArgument:
327
336
  Description: 'Use symbol identifier argument instead of string identifier argument.'
328
337
  Enabled: pending
@@ -3,50 +3,74 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Performance
6
- # Identifies places where numeric argument to BigDecimal should be
7
- # converted to string. Initializing from String is faster
8
- # than from Numeric for BigDecimal.
6
+ # Identifies places where a float argument to BigDecimal should be converted to a string.
7
+ # Initializing from String is faster than from Float for BigDecimal.
8
+ #
9
+ # Also identifies places where an integer string argument to BigDecimal should be converted to
10
+ # an integer. Initializing from Integer is faster than from String for BigDecimal.
9
11
  #
10
12
  # @example
11
13
  # # bad
12
- # BigDecimal(1, 2)
13
- # 4.to_d(6)
14
14
  # BigDecimal(1.2, 3, exception: true)
15
15
  # 4.5.to_d(6, exception: true)
16
16
  #
17
17
  # # good
18
- # BigDecimal('1', 2)
19
- # BigDecimal('4', 6)
20
18
  # BigDecimal('1.2', 3, exception: true)
21
19
  # BigDecimal('4.5', 6, exception: true)
22
20
  #
21
+ # # bad
22
+ # BigDecimal('1', 2)
23
+ # BigDecimal('4', 6)
24
+ #
25
+ # # good
26
+ # BigDecimal(1, 2)
27
+ # 4.to_d(6)
28
+ #
23
29
  class BigDecimalWithNumericArgument < Base
24
30
  extend AutoCorrector
31
+ extend TargetRubyVersion
32
+
33
+ minimum_target_ruby_version 3.1
25
34
 
26
- MSG = 'Convert numeric literal to string and pass it to `BigDecimal`.'
35
+ MSG_FROM_FLOAT_TO_STRING = 'Convert float literal to string and pass it to `BigDecimal`.'
36
+ MSG_FROM_INTEGER_TO_STRING = 'Convert string literal to integer and pass it to `BigDecimal`.'
27
37
  RESTRICT_ON_SEND = %i[BigDecimal to_d].freeze
28
38
 
29
- def_node_matcher :big_decimal_with_numeric_argument?, <<~PATTERN
30
- (send nil? :BigDecimal $numeric_type? ...)
39
+ def_node_matcher :big_decimal_with_numeric_argument, <<~PATTERN
40
+ (send nil? :BigDecimal ${float_type? str_type?} ...)
31
41
  PATTERN
32
42
 
33
- def_node_matcher :to_d?, <<~PATTERN
34
- (send [!nil? $numeric_type?] :to_d ...)
43
+ def_node_matcher :to_d, <<~PATTERN
44
+ (send [!nil? ${float_type? str_type?}] :to_d ...)
35
45
  PATTERN
36
46
 
47
+ # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/MethodLength
37
48
  def on_send(node)
38
- if (numeric = big_decimal_with_numeric_argument?(node))
39
- add_offense(numeric.source_range) do |corrector|
40
- corrector.wrap(numeric, "'", "'")
49
+ if (numeric = big_decimal_with_numeric_argument(node))
50
+ if numeric.numeric_type?
51
+ add_offense(numeric, message: MSG_FROM_FLOAT_TO_STRING) do |corrector|
52
+ corrector.wrap(numeric, "'", "'")
53
+ end
54
+ elsif numeric.value.match?(/\A\d+\z/)
55
+ add_offense(numeric, message: MSG_FROM_INTEGER_TO_STRING) do |corrector|
56
+ corrector.replace(numeric, numeric.value)
57
+ end
41
58
  end
42
- elsif (numeric_to_d = to_d?(node))
43
- add_offense(numeric_to_d.source_range) do |corrector|
44
- big_decimal_args = node.arguments.map(&:source).unshift("'#{numeric_to_d.source}'").join(', ')
59
+ elsif (numeric_to_d = to_d(node))
60
+ if numeric_to_d.numeric_type?
61
+ add_offense(numeric_to_d, message: MSG_FROM_FLOAT_TO_STRING) do |corrector|
62
+ big_decimal_args = node.arguments.map(&:source).unshift("'#{numeric_to_d.source}'").join(', ')
45
63
 
46
- corrector.replace(node, "BigDecimal(#{big_decimal_args})")
64
+ corrector.replace(node, "BigDecimal(#{big_decimal_args})")
65
+ end
66
+ elsif numeric_to_d.value.match?(/\A\d+\z/)
67
+ add_offense(numeric_to_d, message: MSG_FROM_INTEGER_TO_STRING) do |corrector|
68
+ corrector.replace(node, "#{numeric_to_d.value}.to_d")
69
+ end
47
70
  end
48
71
  end
49
72
  end
73
+ # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/MethodLength
50
74
  end
51
75
  end
52
76
  end
@@ -6,6 +6,9 @@ module RuboCop
6
6
  # Identifies unnecessary use of a `block_given?` where explicit check
7
7
  # of block argument would suffice.
8
8
  #
9
+ # NOTE: This cop produces code with significantly worse performance when a
10
+ # block is being passed to the method and as such should not be enabled.
11
+ #
9
12
  # @example
10
13
  # # bad
11
14
  # def method(&block)
@@ -18,14 +18,14 @@ module RuboCop
18
18
  #
19
19
  # [source,ruby]
20
20
  # ----
21
- # `Model.where(id: [1, 2, 3]).select { |m| m.method == true }.size`
21
+ # Model.where(id: [1, 2, 3]).select { |m| m.method == true }.size
22
22
  # ----
23
23
  #
24
24
  # becomes:
25
25
  #
26
26
  # [source,ruby]
27
27
  # ----
28
- # `Model.where(id: [1, 2, 3]).to_a.count { |m| m.method == true }`
28
+ # Model.where(id: [1, 2, 3]).to_a.count { |m| m.method == true }
29
29
  # ----
30
30
  #
31
31
  # @example
@@ -41,7 +41,7 @@ module RuboCop
41
41
  class DoubleStartEndWith < Base
42
42
  extend AutoCorrector
43
43
 
44
- MSG = 'Use `%<receiver>s.%<method>s(%<combined_args>s)` instead of `%<original_code>s`.'
44
+ MSG = 'Use `%<replacement>s` instead of `%<original_code>s`.'
45
45
 
46
46
  def on_or(node)
47
47
  receiver, method, first_call_args, second_call_args = process_source(node)
@@ -50,7 +50,7 @@ module RuboCop
50
50
 
51
51
  combined_args = combine_args(first_call_args, second_call_args)
52
52
 
53
- add_offense(node, message: message(node, receiver, method, combined_args)) do |corrector|
53
+ add_offense(node, message: message(node, receiver, first_call_args, method, combined_args)) do |corrector|
54
54
  autocorrect(corrector, first_call_args, second_call_args, combined_args)
55
55
  end
56
56
  end
@@ -73,10 +73,10 @@ module RuboCop
73
73
  end
74
74
  end
75
75
 
76
- def message(node, receiver, method, combined_args)
77
- format(
78
- MSG, receiver: receiver.source, method: method, combined_args: combined_args, original_code: node.source
79
- )
76
+ def message(node, receiver, first_call_args, method, combined_args)
77
+ dot = first_call_args.first.parent.send_type? ? '.' : '&.'
78
+ replacement = "#{receiver.source}#{dot}#{method}(#{combined_args})"
79
+ format(MSG, replacement: replacement, original_code: node.source)
80
80
  end
81
81
 
82
82
  def combine_args(first_call_args, second_call_args)
@@ -89,16 +89,16 @@ module RuboCop
89
89
 
90
90
  def_node_matcher :two_start_end_with_calls, <<~PATTERN
91
91
  (or
92
- (send $_recv [{:start_with? :end_with?} $_method] $...)
93
- (send _recv _method $...))
92
+ (call $_recv [{:start_with? :end_with?} $_method] $...)
93
+ (call _recv _method $...))
94
94
  PATTERN
95
95
 
96
96
  def_node_matcher :check_with_active_support_aliases, <<~PATTERN
97
97
  (or
98
- (send $_recv
98
+ (call $_recv
99
99
  [{:start_with? :starts_with? :end_with? :ends_with?} $_method]
100
100
  $...)
101
- (send _recv _method $...))
101
+ (call _recv _method $...))
102
102
  PATTERN
103
103
  end
104
104
  end
@@ -72,7 +72,7 @@ module RuboCop
72
72
 
73
73
  def requires_parentheses?(arg)
74
74
  return true if arg.if_type? && arg.ternary?
75
- return true if arg.and_type? || arg.or_type? || arg.range_type?
75
+ return true if arg.operator_keyword? || arg.range_type?
76
76
 
77
77
  call_like?(arg) && requires_parentheses_for_call_like?(arg)
78
78
  end
@@ -130,9 +130,7 @@ module RuboCop
130
130
  end
131
131
 
132
132
  def rewrite_with_modifier(node, parent, new_source)
133
- # FIXME: `|| 2` can be removed when support is limited to RuboCop 1.44 or higher.
134
- # https://github.com/rubocop/rubocop/commit/02d1e5b
135
- indent = ' ' * (configured_indentation_width || 2)
133
+ indent = ' ' * configured_indentation_width
136
134
  padding = "\n#{indent + leading_spaces(node)}"
137
135
  new_source.gsub!("\n", padding)
138
136
 
@@ -48,7 +48,7 @@ module RuboCop
48
48
  RESTRICT_ON_SEND = %i[[] slice first last take length size empty?].freeze
49
49
 
50
50
  def_node_matcher :redundant_chars_call?, <<~PATTERN
51
- (send $(send _ :chars) $_ $...)
51
+ (send $(send !nil? :chars) $_ $...)
52
52
  PATTERN
53
53
 
54
54
  def on_send(node)
@@ -46,7 +46,11 @@ module RuboCop
46
46
  message = format(MSG, current: bad_method, prefer: good_method)
47
47
 
48
48
  add_offense(node.loc.selector, message: message) do |corrector|
49
- string_literal = to_string_literal(replace_str)
49
+ # FIXME: When requiring only RuboCop 1.70.0 and above,
50
+ # `dup` in `replace_str.dup` becomes unnecessary, as
51
+ # frozen strings are handled in the `to_string_literal`
52
+ # implementation. Please remove it.
53
+ string_literal = to_string_literal(replace_str.dup)
50
54
  new_code = "#{receiver.source}#{node.loc.dot.source}#{good_method}(#{string_literal})"
51
55
 
52
56
  corrector.replace(node, new_code)
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Performance
6
+ # Checks for calls to `#bytes` counting method and suggests using `bytesize` instead.
7
+ # The `bytesize` method is more efficient and directly returns the size in bytes,
8
+ # avoiding the intermediate array allocation that `bytes.size` incurs.
9
+ #
10
+ # @safety
11
+ # This cop is unsafe because it assumes that the receiver
12
+ # responds to `#bytesize` method.
13
+ #
14
+ # @example
15
+ # # bad
16
+ # string_var.bytes.count
17
+ # "foobar".bytes.size
18
+ #
19
+ # # good
20
+ # string_var.bytesize
21
+ # "foobar".bytesize
22
+ class StringBytesize < Base
23
+ extend AutoCorrector
24
+
25
+ MSG = 'Use `String#bytesize` instead of calculating the size of the bytes array.'
26
+ RESTRICT_ON_SEND = %i[size length count].freeze
27
+
28
+ def_node_matcher :string_bytes_method?, <<~MATCHER
29
+ (call (call !{nil? int} :bytes) {:size :length :count})
30
+ MATCHER
31
+
32
+ def on_send(node)
33
+ string_bytes_method?(node) do
34
+ range = node.receiver.loc.selector.begin.join(node.source_range.end)
35
+
36
+ add_offense(range) do |corrector|
37
+ corrector.replace(range, 'bytesize')
38
+ end
39
+ end
40
+ end
41
+ alias on_csend on_send
42
+ end
43
+ end
44
+ end
45
+ end
@@ -159,7 +159,7 @@ module RuboCop
159
159
 
160
160
  def array_literal?(node)
161
161
  receiver = node.children.first
162
- receiver&.literal? && receiver&.array_type?
162
+ receiver&.literal? && receiver.array_type?
163
163
  end
164
164
 
165
165
  def autocorrect(corrector, init, range)
@@ -44,6 +44,7 @@ require_relative 'performance/select_map'
44
44
  require_relative 'performance/size'
45
45
  require_relative 'performance/sort_reverse'
46
46
  require_relative 'performance/squeeze'
47
+ require_relative 'performance/string_bytesize'
47
48
  require_relative 'performance/start_with'
48
49
  require_relative 'performance/string_identifier_argument'
49
50
  require_relative 'performance/string_include'
@@ -4,7 +4,7 @@ module RuboCop
4
4
  module Performance
5
5
  # This module holds the RuboCop Performance version information.
6
6
  module Version
7
- STRING = '1.21.1'
7
+ STRING = '1.23.1'
8
8
 
9
9
  def self.document_version
10
10
  STRING.match('\d+\.\d+').to_s
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubocop-performance
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.21.1
4
+ version: 1.23.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bozhidar Batsov
@@ -9,7 +9,7 @@ authors:
9
9
  - Yuji Nakayama
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2024-06-16 00:00:00.000000000 Z
12
+ date: 2025-01-04 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rubocop
@@ -111,6 +111,7 @@ files:
111
111
  - lib/rubocop/cop/performance/sort_reverse.rb
112
112
  - lib/rubocop/cop/performance/squeeze.rb
113
113
  - lib/rubocop/cop/performance/start_with.rb
114
+ - lib/rubocop/cop/performance/string_bytesize.rb
114
115
  - lib/rubocop/cop/performance/string_identifier_argument.rb
115
116
  - lib/rubocop/cop/performance/string_include.rb
116
117
  - lib/rubocop/cop/performance/string_replacement.rb
@@ -129,7 +130,7 @@ metadata:
129
130
  homepage_uri: https://docs.rubocop.org/rubocop-performance/
130
131
  changelog_uri: https://github.com/rubocop/rubocop-performance/blob/master/CHANGELOG.md
131
132
  source_code_uri: https://github.com/rubocop/rubocop-performance/
132
- documentation_uri: https://docs.rubocop.org/rubocop-performance/1.21/
133
+ documentation_uri: https://docs.rubocop.org/rubocop-performance/1.23/
133
134
  bug_tracker_uri: https://github.com/rubocop/rubocop-performance/issues
134
135
  rubygems_mfa_required: 'true'
135
136
  rdoc_options: []
@@ -146,7 +147,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
146
147
  - !ruby/object:Gem::Version
147
148
  version: '0'
148
149
  requirements: []
149
- rubygems_version: 3.6.0.dev
150
+ rubygems_version: 3.6.1
150
151
  specification_version: 4
151
152
  summary: Automatic performance checking tool for Ruby code.
152
153
  test_files: []