class Method
Represents a Ruby method definition wrapper for RBS generation.
Definitions
def initialize(definition)
Initialize a new method wrapper.
Signature
-
parameter
definition
Decode::Definition
The method definition to wrap.
Implementation
def initialize(definition)
super
@signatures = nil
end
def signatures
Extract method signatures from the method definition.
Signature
-
returns
Array
The extracted signatures for this method.
Implementation
def signatures
@signatures ||= extract_signatures
end
def to_rbs_ast(index = nil)
Convert the method definition to RBS AST
Implementation
def to_rbs_ast(index = nil)
method_name = @definition.name
comment = extract_comment(@definition)
overloads = []
if signatures.any?
signatures.each do |signature_string|
method_type = ::RBS::Parser.parse_method_type(signature_string)
overloads << ::RBS::AST::Members::MethodDefinition::Overload.new(
method_type: method_type,
annotations: []
)
end
else
return_type = extract_return_type(@definition, index) || ::RBS::Parser.parse_type("untyped")
parameters = extract_parameters(@definition, index)
block_type = extract_block_type(@definition, index)
method_type = ::RBS::MethodType.new(
type_params: [],
type: ::RBS::Types::Function.new(
required_positionals: parameters,
optional_positionals: [],
rest_positionals: nil,
trailing_positionals: [],
required_keywords: {},
optional_keywords: {},
rest_keywords: nil,
return_type: return_type
),
block: block_type,
location: nil
)
overloads << ::RBS::AST::Members::MethodDefinition::Overload.new(
method_type: method_type,
annotations: []
)
end
kind = @definition.receiver ? :singleton : :instance
::RBS::AST::Members::MethodDefinition.new(
name: method_name.to_sym,
kind: kind,
overloads: overloads,
annotations: [],
location: nil,
comment: comment,
overloading: false,
visibility: :public
)
end
def extract_return_type(definition, index)
Extract return type from method documentation
Implementation
def extract_return_type(definition, index)
# Look for @returns tags in the method's documentation
documentation = definition.documentation
# Find @returns tag
returns_tag = documentation&.filter(Decode::Comment::Returns)&.first
if returns_tag
# Parse the type from the tag
type_string = returns_tag.type.strip
parse_type_string(type_string)
else
# Infer return type based on method name patterns
infer_return_type(definition)
end
end
def extract_parameters(definition, index)
Extract parameter types from method documentation
Implementation
def extract_parameters(definition, index)
documentation = definition.documentation
return [] unless documentation
# Find @parameter tags
param_tags = documentation.filter(Decode::Comment::Parameter).to_a
return [] if param_tags.empty?
param_tags.map do |tag|
name = tag.name
type_string = tag.type.strip
type = parse_type_string(type_string)
::RBS::Types::Function::Param.new(
type: type,
name: name.to_sym
)
end
end
def extract_block_type(definition, index)
Extract block type from method documentation
Implementation
def extract_block_type(definition, index)
documentation = definition.documentation
return nil unless documentation
# Find @yields tags
yields_tag = documentation.filter(Decode::Comment::Yields).first
return nil unless yields_tag
# Extract block parameters from nested @parameter tags
block_params = yields_tag.filter(Decode::Comment::Parameter).map do |param_tag|
name = param_tag.name
type_string = param_tag.type.strip
type = parse_type_string(type_string)
::RBS::Types::Function::Param.new(
type: type,
name: name.to_sym
)
end
# Parse the block signature to determine if it's required
# Check both the directive name and the block signature
block_signature = yields_tag.block
directive_name = yields_tag.directive
required = !directive_name.include?("?") && !block_signature.include?("?") && !block_signature.include?("optional")
# Determine block return type (default to void if not specified)
block_return_type = ::RBS::Parser.parse_type("void")
# Create the block function type
block_function = ::RBS::Types::Function.new(
required_positionals: block_params,
optional_positionals: [],
rest_positionals: nil,
trailing_positionals: [],
required_keywords: {},
optional_keywords: {},
rest_keywords: nil,
return_type: block_return_type
)
# Create and return the block type
::RBS::Types::Block.new(
type: block_function,
required: required,
self_type: nil
)
end
def infer_return_type(definition)
Infer return type based on method patterns and heuristics
Implementation
def infer_return_type(definition)
method_name = definition.name
method_name_str = method_name.to_s
# Methods ending with ? are typically boolean
if method_name_str.end_with?("?")
return ::RBS::Parser.parse_type("bool")
end
# Methods named initialize return void
if method_name == :initialize
return ::RBS::Parser.parse_type("void")
end
# Methods with names that suggest they return self
if method_name_str.match?(/^(add|append|prepend|push|<<|concat|merge!|sort!|reverse!|clear|delete|remove)/)
return ::RBS::Parser.parse_type("self")
end
# Default to untyped
::RBS::Parser.parse_type("untyped")
end
def parse_type_string(type_string)
Parse a type string and convert it to RBS type
Implementation
def parse_type_string(type_string)
type = Types.parse(type_string)
return ::RBS::Parser.parse_type(type.to_rbs)
rescue => error
Console.warn(self, "Failed to parse type string: #{type_string}", error)
return ::RBS::Parser.parse_type("untyped")
end