class RuboCop::Cop::Sorbet::ForbidTStruct
end
def some_method; end
end
@bar = bar
@foo = foo
def initialize(foo:, bar: 0)
sig { params(foo: String, bar: Integer) }
attr_accessor :bar
sig { returns(Integer) }
attr_reader :foo
sig { returns(String) }
extend T::Sig
class MyStruct
# good
end
def some_method; end
prop :bar, Integer, default: 0
const :foo, String
class MyStruct < T::Struct
# bad
@example
Disallow using ‘T::Struct` and `T::Props`.
def initialize_method(indent, props)
def initialize_method(indent, props) # We sort optional keyword arguments after required ones sorted_props = props.sort_by { |prop| prop.default || prop.factory || prop.nilable? ? 1 : 0 } string = +"\n" line = "#{indent}sig { params(#{sorted_props.map(&:initialize_sig_param).join(", ")}).void }\n" if line.length <= max_line_length string << line else string << "#{indent}sig do\n" string << "#{indent} params(\n" sorted_props.each do |prop| string << "#{indent} #{prop.initialize_sig_param}" string << "," if prop != sorted_props.last string << "\n" end string << "#{indent} ).void\n" string << "#{indent}end\n" end line = "#{indent}def initialize(#{sorted_props.map(&:initialize_param).join(", ")})\n" if line.length <= max_line_length string << line else string << "#{indent}def initialize(\n" sorted_props.each do |prop| string << "#{indent} #{prop.initialize_param}" string << "," if prop != sorted_props.last string << "\n" end string << "#{indent})\n" end props.each do |prop| string << "#{indent} #{prop.initialize_assign}\n" end string << "#{indent}end\n" end
def on_class(node)
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
def on_send(node)
def on_send(node) return unless t_props?(node) add_offense(node, message: MSG_PROPS) end
def previous_line_blank?(node)
def previous_line_blank?(node) processed_source.buffer.source_line(node.source_range.line - 1).blank? end