forked from rubocop/rubocop-performance
/
unfreeze_string.rb
47 lines (43 loc) · 1.36 KB
/
unfreeze_string.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# frozen_string_literal: true
module RuboCop
module Cop
module Performance
# In Ruby 2.3 or later, use unary plus operator to unfreeze a string
# literal instead of `String#dup` and `String.new`.
# Unary plus operator is faster than `String#dup`.
#
# NOTE: `String.new` (without operator) is not exactly the same as `+''`.
# These differ in encoding. `String.new.encoding` is always `ASCII-8BIT`.
# However, `(+'').encoding` is the same as script encoding(e.g. `UTF-8`).
# So, if you expect `ASCII-8BIT` encoding, disable this cop.
#
# @example
# # bad
# ''.dup
# "something".dup
# String.new
# String.new('')
# String.new('something')
#
# # good
# +'something'
# +''
class UnfreezeString < Base
MSG = 'Use unary plus to get an unfrozen string literal.'
RESTRICT_ON_SEND = %i[dup new].freeze
def_node_matcher :dup_string?, <<~PATTERN
(send {str dstr} :dup)
PATTERN
def_node_matcher :string_new?, <<~PATTERN
{
(send (const nil? :String) :new {str dstr})
(send (const nil? :String) :new)
}
PATTERN
def on_send(node)
add_offense(node) if dup_string?(node) || string_new?(node)
end
end
end
end
end