class RuboCop::Cop::Style::MutableConstant
This cop checks whether some constant value isn't a mutable literal (e.g. array or hash).
Strict mode can be used to freeze all constants, rather than just literals. Strict mode is considered an experimental feature. It has not been updated with an exhaustive list of all methods that will produce frozen objects so there is a decent chance of getting some false positives. Luckily, there is no harm in freezing an already frozen object.
@example EnforcedStyle: literals (default)
# bad CONST = [1, 2, 3] # good CONST = [1, 2, 3].freeze # good CONST = <<~TESTING.freeze This is a heredoc TESTING # good CONST = Something.new
@example EnforcedStyle: strict
# bad CONST = Something.new # bad CONST = Struct.new do def foo puts 1 end end # good CONST = Something.new.freeze # good CONST = Struct.new do def foo puts 1 end end.freeze
Constants
- MSG
Public Instance Methods
autocorrect(node)
click to toggle source
# File lib/rubocop/cop/style/mutable_constant.rb, line 72 def autocorrect(node) expr = node.source_range lambda do |corrector| splat_value = splat_value(node) if splat_value correct_splat_expansion(corrector, expr, splat_value) elsif node.array_type? && !node.bracketed? corrector.insert_before(expr, '[') corrector.insert_after(expr, ']') elsif requires_parentheses?(node) corrector.insert_before(expr, '(') corrector.insert_after(expr, ')') end corrector.insert_after(expr, '.freeze') end end
on_casgn(node)
click to toggle source
# File lib/rubocop/cop/style/mutable_constant.rb, line 59 def on_casgn(node) _scope, _const_name, value = *node on_assignment(value) end
on_or_asgn(node)
click to toggle source
# File lib/rubocop/cop/style/mutable_constant.rb, line 64 def on_or_asgn(node) lhs, value = *node return unless lhs&.casgn_type? on_assignment(value) end
Private Instance Methods
check(value)
click to toggle source
# File lib/rubocop/cop/style/mutable_constant.rb, line 109 def check(value) range_enclosed_in_parentheses = range_enclosed_in_parentheses?(value) return unless mutable_literal?(value) || range_enclosed_in_parentheses return if FROZEN_STRING_LITERAL_TYPES.include?(value.type) && frozen_string_literals_enabled? add_offense(value) end
correct_splat_expansion(corrector, expr, splat_value)
click to toggle source
# File lib/rubocop/cop/style/mutable_constant.rb, line 138 def correct_splat_expansion(corrector, expr, splat_value) if range_enclosed_in_parentheses?(splat_value) corrector.replace(expr, "#{splat_value.source}.to_a") else corrector.replace(expr, "(#{splat_value.source}).to_a") end end
frozen_string_literal?(node)
click to toggle source
# File lib/rubocop/cop/style/mutable_constant.rb, line 128 def frozen_string_literal?(node) FROZEN_STRING_LITERAL_TYPES.include?(node.type) && frozen_string_literals_enabled? end
immutable_literal?(node)
click to toggle source
# File lib/rubocop/cop/style/mutable_constant.rb, line 124 def immutable_literal?(node) node.nil? || node.immutable_literal? end
mutable_literal?(value)
click to toggle source
# File lib/rubocop/cop/style/mutable_constant.rb, line 120 def mutable_literal?(value) value&.mutable_literal? end
on_assignment(value)
click to toggle source
# File lib/rubocop/cop/style/mutable_constant.rb, line 93 def on_assignment(value) if style == :strict strict_check(value) else check(value) end end
requires_parentheses?(node)
click to toggle source
# File lib/rubocop/cop/style/mutable_constant.rb, line 133 def requires_parentheses?(node) node.range_type? || (node.send_type? && node.loc.dot.nil?) end
strict_check(value)
click to toggle source
# File lib/rubocop/cop/style/mutable_constant.rb, line 101 def strict_check(value) return if immutable_literal?(value) return if operation_produces_immutable_object?(value) return if frozen_string_literal?(value) add_offense(value) end