Class: RuboCop::Cop::Sorbet::RedundantTLetForLiteral
- Inherits:
-
Base
- Object
- Base
- RuboCop::Cop::Sorbet::RedundantTLetForLiteral
- Extended by:
- AutoCorrector
- Includes:
- ConstantScope, TLetCorrection, TargetSorbetVersion
- Defined in:
- lib/rubocop/cop/sorbet/redundant_t_let_for_literal.rb
Overview
Checks for redundant T.let declarations where the first argument
is a literal whose type Sorbet can infer automatically, so wrapping
it in T.let is redundant.
Simple literals (strings, symbols, integers, floats, regexps) infer as
their own class. Regexp literals are the only simple literals whose
inference survives a .freeze call (Sorbet 0.6.13304+), so
T.let(/foo/.freeze, Regexp) is also redundant; other frozen simple
literals (e.g. "hello".freeze) are not inferred and still need T.let.
Array literals of simple literals are also inferred:
- A frozen array (
[...].freeze) infers as a fixed-size tuple, which is a subtype of the annotatedT::Array, so the annotation is redundant. - An unfrozen array infers as
T::Array[<element type>]. It is only flagged when that inferred type matches the annotation exactly, to avoid silently widening (e.g.["a", nil]infers a nilable element).
Hashes are excluded: Sorbet infers hash literals as T.untyped, so the
annotation is required.
Constant Summary collapse
- MSG =
"Redundant `T.let` for %{type} literal. Sorbet can infer this type automatically."- LITERAL_TYPE_TO_CLASS =
Simple literal node types Sorbet infers, mapped to the class name. Interpolated strings/symbols (
dstr/dsym) infer asString/Symbol. { dstr: :String, dsym: :Symbol, float: :Float, int: :Integer, regexp: :Regexp, str: :String, sym: :Symbol, }.freeze
- ARRAY_ELEMENT_TYPES =
Element node types allowed inside an inferable array literal: the literals whose class Sorbet reflects into the array's element type. Regexps and ranges, by contrast, degrade the array to
T.untyped, so they are excluded. Interpolated strings/symbols (dstr/dsym) infer asString/Symbol, the same as their plain literal forms. [:dstr, :dsym, :str, :sym, :int, :float, :true, :false, :nil].freeze
- ELEMENT_TYPE_TO_CLASS =
Element node types whose inferred class is unambiguous, used to derive the element type of an unfrozen array literal.
{ dstr: "String", dsym: "Symbol", float: "Float", int: "Integer", str: "String", sym: "Symbol", }.freeze
Instance Method Summary collapse
- #on_casgn(node) ⇒ Object
- #t_let_with_array?(node) ⇒ Object
- #t_let_with_literal_and_class?(node) ⇒ Object
Methods included from TargetSorbetVersion
#enabled_for_sorbet_static_version?, included, #read_sorbet_static_version_from_bundler_lock_file, #sorbet_enabled?, #target_sorbet_static_version_from_bundler_lock_file
Instance Method Details
#on_casgn(node) ⇒ Object
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
# File 'lib/rubocop/cop/sorbet/redundant_t_let_for_literal.rb', line 123 def on_casgn(node) return unless statically_scoped?(node) t_let_with_literal_and_class?(node) do |value_node, class_name| literal_node = inferable_literal_node(value_node) next unless literal_node next unless LITERAL_TYPE_TO_CLASS[literal_node.type] == class_name register_offense(node, value_node, class_name) end return unless enabled_for_sorbet_static_version? t_let_with_array?(node) do |value_node, type_node| frozen = value_node.send_type? array_node = frozen ? value_node.receiver : value_node next unless inferable_array?(array_node) next unless redundant_array_annotation?(array_node, type_node, frozen: frozen) register_offense(node, value_node, :Array) end end |
#t_let_with_array?(node) ⇒ Object
119 120 121 |
# File 'lib/rubocop/cop/sorbet/redundant_t_let_for_literal.rb', line 119 def_node_matcher :t_let_with_array?, <<~PATTERN (casgn _ _ (send (const {nil? cbase} :T) :let ${array (send array :freeze)} $_)) PATTERN |
#t_let_with_literal_and_class?(node) ⇒ Object
114 115 116 |
# File 'lib/rubocop/cop/sorbet/redundant_t_let_for_literal.rb', line 114 def_node_matcher :t_let_with_literal_and_class?, <<~PATTERN (casgn _ _ (send (const {nil? cbase} :T) :let ${literal? (send (regexp ...) :freeze)} (const nil? $_))) PATTERN |