Class: RuboCop::Cop::Sorbet::ForbidTStruct

Inherits:
Base
  • Object
show all
Extended by:
AutoCorrector
Includes:
Alignment, CommentsHelp, RangeHelp
Defined in:
lib/rubocop/cop/sorbet/forbid_t_struct.rb

Overview

Disallow using ‘T::Struct` and `T::Props`.

Examples:


# bad
class MyStruct < T::Struct
  const :foo, String
  prop :bar, Integer, default: 0

  def some_method; end
end

# good
class MyStruct
  extend T::Sig

  sig { returns(String) }
  attr_reader :foo

  sig { returns(Integer) }
  attr_accessor :bar

  sig { params(foo: String, bar: Integer) }
  def initialize(foo:, bar: 0)
    @foo = foo
    @bar = bar
  end

  def some_method; end
end

Defined Under Namespace

Classes: Property, TStructWalker

Constant Summary collapse

RESTRICT_ON_SEND =
[:include, :prepend, :extend].freeze
MSG_STRUCT =
"Using `T::Struct` or its variants is deprecated."
MSG_PROPS =
"Using `T::Props` or its variants is deprecated."

Instance Method Summary collapse

Instance Method Details

#on_class(node) ⇒ Object



169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
# File 'lib/rubocop/cop/sorbet/forbid_t_struct.rb', line 169

def on_class(node)
  return unless t_struct?(node.parent_class)

  add_offense(node, message: MSG_STRUCT) do |corrector|
    walker = TStructWalker.new
    walker.walk(node.body)

    range = range_between(node.identifier.source_range.end_pos, node.parent_class.source_range.end_pos)
    corrector.remove(range)
    next if node.single_line?

    unless walker.has_extend_t_sig
      indent = offset(node)
      corrector.insert_after(node.identifier, "\n#{indent}  extend T::Sig\n")
    end

    first_prop = walker.props.first
    walker.props.each do |prop|
      node = prop.node
      indent = offset(node)
      line_range = range_by_whole_lines(prop.node.source_range)
      new_line = prop != first_prop && !previous_line_blank?(node)
      trailing_comments = processed_source.each_comment_in_lines(line_range.line..line_range.line)

      corrector.replace(
        line_range,
        "#{new_line ? "\n" : ""}" \
          "#{trailing_comments.map { |comment| "#{indent}#{comment.text}\n" }.join}" \
          "#{indent}#{prop.attr_sig}\n#{indent}#{prop.attr_accessor}",
      )
    end

    last_prop = walker.props.last
    if last_prop
      indent = offset(last_prop.node)
      line_range = range_by_whole_lines(last_prop.node.source_range, include_final_newline: true)
      corrector.insert_after(line_range, initialize_method(indent, walker.props))
    end
  end
end

#on_send(node) ⇒ Object



210
211
212
213
214
# File 'lib/rubocop/cop/sorbet/forbid_t_struct.rb', line 210

def on_send(node)
  return unless t_props?(node)

  add_offense(node, message: MSG_PROPS)
end

#t_props?(node) ⇒ Object



167
# File 'lib/rubocop/cop/sorbet/forbid_t_struct.rb', line 167

def_node_matcher(:t_props?, "(send nil? {:include :prepend :extend} `(const (const {nil? cbase} :T) :Props))")

#t_struct?(node) ⇒ Object



162
163
164
# File 'lib/rubocop/cop/sorbet/forbid_t_struct.rb', line 162

def_node_matcher(:t_struct?, <<~PATTERN)
  (const (const {nil? cbase} :T) {:Struct :ImmutableStruct :InexactStruct})
PATTERN