/
redundant_freeze.rb
67 lines (56 loc) · 1.78 KB
/
redundant_freeze.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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# frozen_string_literal: true
module RuboCop
module Cop
module Style
# This cop check for uses of Object#freeze on immutable objects.
#
# @example
# # bad
# CONST = 1.freeze
#
# # good
# CONST = 1
class RedundantFreeze < Cop
include FrozenStringLiteral
MSG = 'Do not freeze immutable objects, as freezing them has no ' \
'effect.'.freeze
def on_send(node)
return unless node.receiver && node.method?(:freeze) &&
(immutable_literal?(node.receiver) ||
operation_produces_immutable_object?(node.receiver))
add_offense(node)
end
def autocorrect(node)
lambda do |corrector|
corrector.remove(node.loc.dot)
corrector.remove(node.loc.selector)
end
end
private
def immutable_literal?(node)
node = strip_parenthesis(node)
return true if node.immutable_literal?
FROZEN_STRING_LITERAL_TYPES.include?(node.type) &&
frozen_string_literals_enabled?
end
def strip_parenthesis(node)
if node.begin_type? && node.children.first
node.children.first
else
node
end
end
def_node_matcher :operation_produces_immutable_object?, <<-PATTERN
{
(begin (send {float int} {:+ :- :* :** :/ :% :<<} _))
(begin (send !(str _) {:+ :- :* :** :/ :%} {float int}))
(begin (send _ {:== :=== :!= :<= :>= :< :>} _))
(send (const nil? :ENV) :[] _)
(send _ {:count :length :size} ...)
(block (send _ {:count :length :size} ...) ...)
}
PATTERN
end
end
end
end