rubocop-performance 1.6.0 → 1.6.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 5e13aa59742e803b8445a8149c382c50fdbaab1d
4
- data.tar.gz: 55d59fd7bb03179a9055e46613a3d1f2d2888967
2
+ SHA256:
3
+ metadata.gz: 111d420207542c8522d9f34b5b8bf24356572b5fbcf0c11dfcb1e7f738a4c76f
4
+ data.tar.gz: 97632031f51e154320bc3d585da448740596436882b67277f1b5d26ddfe55fba
5
5
  SHA512:
6
- metadata.gz: 01a28951033ec2b751828d6df2a80f63a5a2d9e9d9576a2228c12b645087b2a631c3676757bd5037e3eecc22d89a7ef28765194545393210a9068da92931d065
7
- data.tar.gz: 79b46ec046a4c1bade7e1e9dd07a5fd892f25280565adb6a91d8dddcce3931722cecf93fb72d4d0e32b7d40441829d26883973b11b5139389b6cebf91bdca435
6
+ metadata.gz: a36e6950e6fe7847303c87862df76767d32c4f68640c229ad4ceb6115d4ae2093be18a8296c2e49324c67e8eb06dd99db42f8823586f1b572e10a74693b831d1
7
+ data.tar.gz: 782352b1a7c420ac3c5498aeff749577e6280fb35d6e36844ae875511e9b6b44becfd9a2789d1b4c672cb71a91b8ab1cc63c89ec41abda8d1f34f1dacd26a07c
data/README.md CHANGED
@@ -74,7 +74,7 @@ Performance/Size:
74
74
 
75
75
  ## Documentation
76
76
 
77
- You can read a lot more about RuboCop Performance in its [official docs](https://docs.rubocop.org/projects/performance/).
77
+ You can read a lot more about RuboCop Performance in its [official docs](https://docs.rubocop.org/rubocop-performance/).
78
78
 
79
79
  ## Contributing
80
80
 
@@ -58,11 +58,13 @@ Performance/Count:
58
58
  Performance/DeletePrefix:
59
59
  Description: 'Use `delete_prefix` instead of `gsub`.'
60
60
  Enabled: true
61
+ SafeMultiline: true
61
62
  VersionAdded: '1.6'
62
63
 
63
64
  Performance/DeleteSuffix:
64
65
  Description: 'Use `delete_suffix` instead of `gsub`.'
65
66
  Enabled: true
67
+ SafeMultiline: true
66
68
  VersionAdded: '1.6'
67
69
 
68
70
  Performance/Detect:
@@ -99,8 +101,9 @@ Performance/EndWith:
99
101
  SafeAutoCorrect: false
100
102
  AutoCorrect: false
101
103
  Enabled: true
104
+ SafeMultiline: true
102
105
  VersionAdded: '0.36'
103
- VersionChanged: '0.44'
106
+ VersionChanged: '1.6'
104
107
 
105
108
  Performance/FixedSize:
106
109
  Description: 'Do not compute the size of statically sized objects except in constants.'
@@ -193,8 +196,9 @@ Performance/StartWith:
193
196
  SafeAutoCorrect: false
194
197
  AutoCorrect: false
195
198
  Enabled: true
199
+ SafeMultiline: true
196
200
  VersionAdded: '0.36'
197
- VersionChanged: '0.44'
201
+ VersionChanged: '1.6'
198
202
 
199
203
  Performance/StringReplacement:
200
204
  Description: >-
@@ -4,21 +4,52 @@ module RuboCop
4
4
  module Cop
5
5
  # Common functionality for handling regexp metacharacters.
6
6
  module RegexpMetacharacter
7
- def literal_at_start?(regex_str)
7
+ private
8
+
9
+ def literal_at_start?(regexp)
10
+ return true if literal_at_start_with_backslash_a?(regexp)
11
+
12
+ !safe_multiline? && literal_at_start_with_caret?(regexp)
13
+ end
14
+
15
+ def literal_at_end?(regexp)
16
+ return true if literal_at_end_with_backslash_z?(regexp)
17
+
18
+ !safe_multiline? && literal_at_end_with_dollar?(regexp)
19
+ end
20
+
21
+ def literal_at_start_with_backslash_a?(regex_str)
22
+ # is this regexp 'literal' in the sense of only matching literal
23
+ # chars, rather than using metachars like `.` and `*` and so on?
24
+ # also, is it anchored at the start of the string?
25
+ # (tricky: \s, \d, and so on are metacharacters, but other characters
26
+ # escaped with a slash are just literals. LITERAL_REGEX takes all
27
+ # that into account.)
28
+ /\A\\A(?:#{Util::LITERAL_REGEX})+\z/.match?(regex_str)
29
+ end
30
+
31
+ def literal_at_start_with_caret?(regex_str)
8
32
  # is this regexp 'literal' in the sense of only matching literal
9
33
  # chars, rather than using metachars like `.` and `*` and so on?
10
34
  # also, is it anchored at the start of the string?
11
35
  # (tricky: \s, \d, and so on are metacharacters, but other characters
12
36
  # escaped with a slash are just literals. LITERAL_REGEX takes all
13
37
  # that into account.)
14
- regex_str =~ /\A(\\A|\^)(?:#{Util::LITERAL_REGEX})+\z/
38
+ /\A\^(?:#{Util::LITERAL_REGEX})+\z/.match?(regex_str)
15
39
  end
16
40
 
17
- def literal_at_end?(regex_str)
41
+ def literal_at_end_with_backslash_z?(regex_str)
18
42
  # is this regexp 'literal' in the sense of only matching literal
19
43
  # chars, rather than using metachars like . and * and so on?
20
44
  # also, is it anchored at the end of the string?
21
- regex_str =~ /\A(?:#{Util::LITERAL_REGEX})+(\\z|\$)\z/
45
+ /\A(?:#{Util::LITERAL_REGEX})+\\z\z/.match?(regex_str)
46
+ end
47
+
48
+ def literal_at_end_with_dollar?(regex_str)
49
+ # is this regexp 'literal' in the sense of only matching literal
50
+ # chars, rather than using metachars like . and * and so on?
51
+ # also, is it anchored at the end of the string?
52
+ /\A(?:#{Util::LITERAL_REGEX})+\$\z/.match?(regex_str)
22
53
  end
23
54
 
24
55
  def drop_start_metacharacter(regexp_string)
@@ -36,6 +67,10 @@ module RuboCop
36
67
  regexp_string.chop # drop `$` anchor
37
68
  end
38
69
  end
70
+
71
+ def safe_multiline?
72
+ cop_config.fetch('SafeMultiline', true)
73
+ end
39
74
  end
40
75
  end
41
76
  end
@@ -5,24 +5,44 @@ module RuboCop
5
5
  module Performance
6
6
  # In Ruby 2.5, `String#delete_prefix` has been added.
7
7
  #
8
- # This cop identifies places where `gsub(/\Aprefix/, '')`
8
+ # This cop identifies places where `gsub(/\Aprefix/, '')` and `sub(/\Aprefix/, '')`
9
9
  # can be replaced by `delete_prefix('prefix')`.
10
10
  #
11
- # The `delete_prefix('prefix')` method is faster than
12
- # `gsub(/\Aprefix/, '')`.
11
+ # This cop has `SafeMultiline` configuration option that `true` by default because
12
+ # `^prefix` is unsafe as it will behave incompatible with `delete_prefix`
13
+ # for receiver is multiline string.
14
+ #
15
+ # The `delete_prefix('prefix')` method is faster than `gsub(/\Aprefix/, '')`.
13
16
  #
14
17
  # @example
15
18
  #
16
19
  # # bad
17
20
  # str.gsub(/\Aprefix/, '')
18
21
  # str.gsub!(/\Aprefix/, '')
19
- # str.gsub(/^prefix/, '')
20
- # str.gsub!(/^prefix/, '')
22
+ #
23
+ # str.sub(/\Aprefix/, '')
24
+ # str.sub!(/\Aprefix/, '')
21
25
  #
22
26
  # # good
23
27
  # str.delete_prefix('prefix')
24
28
  # str.delete_prefix!('prefix')
25
29
  #
30
+ # @example SafeMultiline: true (default)
31
+ #
32
+ # # good
33
+ # str.gsub(/^prefix/, '')
34
+ # str.gsub!(/^prefix/, '')
35
+ # str.sub(/^prefix/, '')
36
+ # str.sub!(/^prefix/, '')
37
+ #
38
+ # @example SafeMultiline: false
39
+ #
40
+ # # bad
41
+ # str.gsub(/^prefix/, '')
42
+ # str.gsub!(/^prefix/, '')
43
+ # str.sub(/^prefix/, '')
44
+ # str.sub!(/^prefix/, '')
45
+ #
26
46
  class DeletePrefix < Cop
27
47
  extend TargetRubyVersion
28
48
  include RegexpMetacharacter
@@ -33,15 +53,17 @@ module RuboCop
33
53
 
34
54
  PREFERRED_METHODS = {
35
55
  gsub: :delete_prefix,
36
- gsub!: :delete_prefix!
56
+ gsub!: :delete_prefix!,
57
+ sub: :delete_prefix,
58
+ sub!: :delete_prefix!
37
59
  }.freeze
38
60
 
39
- def_node_matcher :gsub_method?, <<~PATTERN
40
- (send $!nil? ${:gsub :gsub!} (regexp (str $#literal_at_start?) (regopt)) (str $_))
61
+ def_node_matcher :delete_prefix_candidate?, <<~PATTERN
62
+ (send $!nil? ${:gsub :gsub! :sub :sub!} (regexp (str $#literal_at_start?) (regopt)) (str $_))
41
63
  PATTERN
42
64
 
43
65
  def on_send(node)
44
- gsub_method?(node) do |_, bad_method, _, replace_string|
66
+ delete_prefix_candidate?(node) do |_, bad_method, _, replace_string|
45
67
  return unless replace_string.blank?
46
68
 
47
69
  good_method = PREFERRED_METHODS[bad_method]
@@ -53,7 +75,7 @@ module RuboCop
53
75
  end
54
76
 
55
77
  def autocorrect(node)
56
- gsub_method?(node) do |receiver, bad_method, regexp_str, _|
78
+ delete_prefix_candidate?(node) do |receiver, bad_method, regexp_str, _|
57
79
  lambda do |corrector|
58
80
  good_method = PREFERRED_METHODS[bad_method]
59
81
  regexp_str = drop_start_metacharacter(regexp_str)
@@ -62,7 +84,9 @@ module RuboCop
62
84
 
63
85
  new_code = "#{receiver.source}.#{good_method}(#{string_literal})"
64
86
 
65
- corrector.replace(node, new_code)
87
+ # TODO: `source_range` is no longer required when RuboCop 0.81 or lower support will be dropped.
88
+ # https://github.com/rubocop-hq/rubocop/commit/82eb350d2cba16
89
+ corrector.replace(node.source_range, new_code)
66
90
  end
67
91
  end
68
92
  end
@@ -5,24 +5,44 @@ module RuboCop
5
5
  module Performance
6
6
  # In Ruby 2.5, `String#delete_suffix` has been added.
7
7
  #
8
- # This cop identifies places where `gsub(/suffix\z/, '')`
8
+ # This cop identifies places where `gsub(/suffix\z/, '')` and `sub(/suffix\z/, '')`
9
9
  # can be replaced by `delete_suffix('suffix')`.
10
10
  #
11
- # The `delete_suffix('suffix')` method is faster than
12
- # `gsub(/suffix\z/, '')`.
11
+ # This cop has `SafeMultiline` configuration option that `true` by default because
12
+ # `suffix$` is unsafe as it will behave incompatible with `delete_suffix?`
13
+ # for receiver is multiline string.
14
+ #
15
+ # The `delete_suffix('suffix')` method is faster than `gsub(/suffix\z/, '')`.
13
16
  #
14
17
  # @example
15
18
  #
16
19
  # # bad
17
20
  # str.gsub(/suffix\z/, '')
18
21
  # str.gsub!(/suffix\z/, '')
19
- # str.gsub(/suffix$/, '')
20
- # str.gsub!(/suffix$/, '')
22
+ #
23
+ # str.sub(/suffix\z/, '')
24
+ # str.sub!(/suffix\z/, '')
21
25
  #
22
26
  # # good
23
27
  # str.delete_suffix('suffix')
24
28
  # str.delete_suffix!('suffix')
25
29
  #
30
+ # @example SafeMultiline: true (default)
31
+ #
32
+ # # good
33
+ # str.gsub(/suffix$/, '')
34
+ # str.gsub!(/suffix$/, '')
35
+ # str.sub(/suffix$/, '')
36
+ # str.sub!(/suffix$/, '')
37
+ #
38
+ # @example SafeMultiline: false
39
+ #
40
+ # # bad
41
+ # str.gsub(/suffix$/, '')
42
+ # str.gsub!(/suffix$/, '')
43
+ # str.sub(/suffix$/, '')
44
+ # str.sub!(/suffix$/, '')
45
+ #
26
46
  class DeleteSuffix < Cop
27
47
  extend TargetRubyVersion
28
48
  include RegexpMetacharacter
@@ -33,15 +53,17 @@ module RuboCop
33
53
 
34
54
  PREFERRED_METHODS = {
35
55
  gsub: :delete_suffix,
36
- gsub!: :delete_suffix!
56
+ gsub!: :delete_suffix!,
57
+ sub: :delete_suffix,
58
+ sub!: :delete_suffix!
37
59
  }.freeze
38
60
 
39
- def_node_matcher :gsub_method?, <<~PATTERN
40
- (send $!nil? ${:gsub :gsub!} (regexp (str $#literal_at_end?) (regopt)) (str $_))
61
+ def_node_matcher :delete_suffix_candidate?, <<~PATTERN
62
+ (send $!nil? ${:gsub :gsub! :sub :sub!} (regexp (str $#literal_at_end?) (regopt)) (str $_))
41
63
  PATTERN
42
64
 
43
65
  def on_send(node)
44
- gsub_method?(node) do |_, bad_method, _, replace_string|
66
+ delete_suffix_candidate?(node) do |_, bad_method, _, replace_string|
45
67
  return unless replace_string.blank?
46
68
 
47
69
  good_method = PREFERRED_METHODS[bad_method]
@@ -53,7 +75,7 @@ module RuboCop
53
75
  end
54
76
 
55
77
  def autocorrect(node)
56
- gsub_method?(node) do |receiver, bad_method, regexp_str, _|
78
+ delete_suffix_candidate?(node) do |receiver, bad_method, regexp_str, _|
57
79
  lambda do |corrector|
58
80
  good_method = PREFERRED_METHODS[bad_method]
59
81
  regexp_str = drop_end_metacharacter(regexp_str)
@@ -62,7 +84,9 @@ module RuboCop
62
84
 
63
85
  new_code = "#{receiver.source}.#{good_method}(#{string_literal})"
64
86
 
65
- corrector.replace(node, new_code)
87
+ # TODO: `source_range` is no longer required when RuboCop 0.81 or lower support will be dropped.
88
+ # https://github.com/rubocop-hq/rubocop/commit/82eb350d2cba16
89
+ corrector.replace(node.source_range, new_code)
66
90
  end
67
91
  end
68
92
  end
@@ -3,8 +3,11 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Performance
6
- # This cop identifies unnecessary use of a regex where `String#end_with?`
7
- # would suffice.
6
+ # This cop identifies unnecessary use of a regex where `String#end_with?` would suffice.
7
+ #
8
+ # This cop has `SafeMultiline` configuration option that `true` by default because
9
+ # `end$` is unsafe as it will behave incompatible with `end_with?`
10
+ # for receiver is multiline string.
8
11
  #
9
12
  # @example
10
13
  # # bad
@@ -15,6 +18,22 @@ module RuboCop
15
18
  # 'abc'.match(/bc\Z/)
16
19
  # /bc\Z/.match('abc')
17
20
  #
21
+ # # good
22
+ # 'abc'.end_with?('bc')
23
+ #
24
+ # @example SafeMultiline: true (default)
25
+ #
26
+ # # good
27
+ # 'abc'.match?(/bc$/)
28
+ # /bc$/.match?('abc')
29
+ # 'abc' =~ /bc$/
30
+ # /bc$/ =~ 'abc'
31
+ # 'abc'.match(/bc$/)
32
+ # /bc$/.match('abc')
33
+ #
34
+ # @example SafeMultiline: false
35
+ #
36
+ # # bad
18
37
  # 'abc'.match?(/bc$/)
19
38
  # /bc$/.match?('abc')
20
39
  # 'abc' =~ /bc$/
@@ -22,8 +41,6 @@ module RuboCop
22
41
  # 'abc'.match(/bc$/)
23
42
  # /bc$/.match('abc')
24
43
  #
25
- # # good
26
- # 'abc'.end_with?('bc')
27
44
  class EndWith < Cop
28
45
  include RegexpMetacharacter
29
46
 
@@ -3,8 +3,11 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Performance
6
- # This cop identifies unnecessary use of a regex where
7
- # `String#start_with?` would suffice.
6
+ # This cop identifies unnecessary use of a regex where `String#start_with?` would suffice.
7
+ #
8
+ # This cop has `SafeMultiline` configuration option that `true` by default because
9
+ # `^start` is unsafe as it will behave incompatible with `start_with?`
10
+ # for receiver is multiline string.
8
11
  #
9
12
  # @example
10
13
  # # bad
@@ -15,6 +18,22 @@ module RuboCop
15
18
  # 'abc'.match(/\Aab/)
16
19
  # /\Aab/.match('abc')
17
20
  #
21
+ # # good
22
+ # 'abc'.start_with?('ab')
23
+ #
24
+ # @example SafeMultiline: true (default)
25
+ #
26
+ # # good
27
+ # 'abc'.match?(/^ab/)
28
+ # /^ab/.match?('abc')
29
+ # 'abc' =~ /^ab/
30
+ # /^ab/ =~ 'abc'
31
+ # 'abc'.match(/^ab/)
32
+ # /^ab/.match('abc')
33
+ #
34
+ # @example SafeMultiline: false
35
+ #
36
+ # # bad
18
37
  # 'abc'.match?(/^ab/)
19
38
  # /^ab/.match?('abc')
20
39
  # 'abc' =~ /^ab/
@@ -22,8 +41,6 @@ module RuboCop
22
41
  # 'abc'.match(/^ab/)
23
42
  # /^ab/.match('abc')
24
43
  #
25
- # # good
26
- # 'abc'.start_with?('ab')
27
44
  class StartWith < Cop
28
45
  include RegexpMetacharacter
29
46
 
@@ -7,7 +7,7 @@ module RuboCop
7
7
  # literal instead of `String#dup` and `String.new`.
8
8
  # Unary plus operator is faster than `String#dup`.
9
9
  #
10
- # Note: `String.new` (without operator) is not exactly the same as `+''`.
10
+ # NOTE: `String.new` (without operator) is not exactly the same as `+''`.
11
11
  # These differ in encoding. `String.new.encoding` is always `ASCII-8BIT`.
12
12
  # However, `(+'').encoding` is the same as script encoding(e.g. `UTF-8`).
13
13
  # So, if you expect `ASCII-8BIT` encoding, disable this cop.
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Performance
5
5
  module Version
6
- STRING = '1.6.0'
6
+ STRING = '1.6.1'
7
7
  end
8
8
  end
9
9
  end
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.6.0
4
+ version: 1.6.1
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: 2020-05-21 00:00:00.000000000 Z
13
+ date: 2020-06-05 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rubocop
@@ -91,10 +91,10 @@ homepage: https://github.com/rubocop-hq/rubocop-performance
91
91
  licenses:
92
92
  - MIT
93
93
  metadata:
94
- homepage_uri: https://docs.rubocop.org/projects/performance/
94
+ homepage_uri: https://docs.rubocop.org/rubocop-performance/
95
95
  changelog_uri: https://github.com/rubocop-hq/rubocop-performance/blob/master/CHANGELOG.md
96
96
  source_code_uri: https://github.com/rubocop-hq/rubocop-performance/
97
- documentation_uri: https://docs.rubocop.org/projects/performance/
97
+ documentation_uri: https://docs.rubocop.org/rubocop-performance/
98
98
  bug_tracker_uri: https://github.com/rubocop-hq/rubocop-performance/issues
99
99
  post_install_message:
100
100
  rdoc_options: []
@@ -111,8 +111,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
111
111
  - !ruby/object:Gem::Version
112
112
  version: '0'
113
113
  requirements: []
114
- rubyforge_project:
115
- rubygems_version: 2.6.14.4
114
+ rubygems_version: 3.1.3
116
115
  signing_key:
117
116
  specification_version: 4
118
117
  summary: Automatic performance checking tool for Ruby code.