Module: Solargraph::RbsTranslator

Defined in:
lib/solargraph/rbs_translator.rb

Overview

Convert RBS types to complex types and pins.

Constant Summary collapse

RBS_TO_YARD_TYPE =
{
  'bool' => 'Boolean',
  'string' => 'String',
  'int' => 'Integer',
  'untyped' => '',
  'NilClass' => 'nil'
}

Class Method Summary collapse

Class Method Details

.build_unique_type(type_name, type_args = []) ⇒ ComplexType::UniqueType

Parameters:

  • type_name (RBS::TypeName)
  • type_args (Enumerable<RBS::Types::Bases::Base>) (defaults to: [])

Returns:



100
101
102
103
104
105
106
107
108
109
110
# File 'lib/solargraph/rbs_translator.rb', line 100

def self.build_unique_type(type_name, type_args = [])
  base = RBS_TO_YARD_TYPE[type_name.relative!.to_s] || type_name.relative!.to_s
  params = type_args.map do |a|
    RbsTranslator.to_complex_type(a)
  end
  if base == 'Hash' && params.length == 2
    ComplexType::UniqueType.new(base, [params.first], [params.last], rooted: true, parameters_type: :hash)
  else
    ComplexType::UniqueType.new(base, [], params.reject(&:undefined?), rooted: true, parameters_type: :list)
  end
end

.to_complex_type(type) ⇒ ComplexType

Parameters:

  • type (RBS::Types::Bases::Base)

Returns:



17
18
19
20
# File 'lib/solargraph/rbs_translator.rb', line 17

def self.to_complex_type(type)
  tag = type_to_tag(type)
  ComplexType.try_parse(tag).force_rooted
end

.to_parameter_pin(param_type, name, decl, closure) ⇒ Pin::Parameter

Parameters:

  • param_type (RBS::Types::Function::Param)
  • name (String)
  • decl (Symbol)
  • closure (Pin::Closure)

Returns:



27
28
29
30
31
32
33
34
35
36
# File 'lib/solargraph/rbs_translator.rb', line 27

def self.to_parameter_pin(param_type, name, decl, closure)
  return_type = if decl == :restarg
    ComplexType.parse('Array')
  elsif decl == :kwrestarg
    ComplexType.parse('Hash{Symbol => Object}')
  else
    RbsTranslator.to_complex_type(param_type.type)
  end
  Solargraph::Pin::Parameter.new(decl: decl, name: name, closure: closure, return_type: return_type, source: :rbs, type_location: to_sg_location(param_type.location) || closure.type_location)
end

.to_parameter_pins(method_type, closure, parameter_names = []) ⇒ Array<Pin::Parameter>

Parameters:

  • method_type (RBS::MethodType)
  • closure (Pin::Closure)
  • parameter_names (Array<String>) (defaults to: [])

Returns:



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/solargraph/rbs_translator.rb', line 42

def self.to_parameter_pins method_type, closure, parameter_names = []
  if defined?(RBS::Types::UntypedFunction) && method_type.type.is_a?(RBS::Types::UntypedFunction)
    return [
      Solargraph::Pin::Parameter.new(decl: :restarg, name: 'arg', closure: closure, source: :rbs)
    ]
  end

  arg_num = 0
  params = []
  method_type.type.required_positionals.each do |param|
    params.push RbsTranslator.to_parameter_pin(param, param.name&.to_s || parameter_names[arg_num] || "arg_#{arg_num}", :arg, closure)
    arg_num += 1
  end
  method_type.type.optional_positionals.each do |param|
    params.push RbsTranslator.to_parameter_pin(param, param.name&.to_s || parameter_names[arg_num] || "arg_#{arg_num}", :optarg, closure)
    arg_num += 1
  end
  if method_type.type.rest_positionals
    params.push RbsTranslator.to_parameter_pin(method_type.type.rest_positionals, method_type.type.rest_positionals.name&.to_s || parameter_names[arg_num] || "arg_#{arg_num}", :restarg, closure)
    arg_num += 1
  end
  method_type.type.required_keywords.each do |param|
    params.push RbsTranslator.to_parameter_pin(param.last, param.first.to_s, :kwarg, closure)
    arg_num += 1
  end
  method_type.type.optional_keywords.each do |param|
    params.push RbsTranslator.to_parameter_pin(param.last, param.first.to_s, :kwoptarg, closure)
    arg_num += 1
  end
  if method_type.type.rest_keywords
    params.push RbsTranslator.to_parameter_pin(method_type.type.rest_keywords, method_type.type.rest_keywords.name&.to_s || parameter_names[arg_num] || "arg_#{arg_num}", :kwrestarg, closure)
  end
  params
end

.to_sg_location(location) ⇒ Solargraph::Location?

Parameters:

  • location (RBS::Location, nil)

Returns:



114
115
116
117
118
119
120
121
# File 'lib/solargraph/rbs_translator.rb', line 114

def self.to_sg_location(location)
  return nil if location&.name.nil?

  start_pos = Position.new(location.start_line - 1, location.start_column)
  end_pos = Position.new(location.end_line - 1, location.end_column)
  range = Range.new(start_pos, end_pos)
  Location.new(location.name.to_s, range)
end

.to_signature(method_type, closure, parameter_names = []) ⇒ Pin::Signature

Parameters:

  • method_type (RBS::MethodType)
  • closure (Pin::Closure)
  • parameter_names (Array<String>) (defaults to: [])

Returns:



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/solargraph/rbs_translator.rb', line 81

def self.to_signature method_type, closure, parameter_names = []
  # There may be edge cases here around different signatures
  # having different type params / orders - we may need to match
  # this data model and have generics live in signatures to
  # handle those correctly
  generics = method_type.type_params.map(&:name).map(&:to_s).uniq
  parameters = to_parameter_pins(method_type, closure, parameter_names)
  return_type = to_complex_type(method_type.type.return_type)
  block = if method_type.block
    block_parameters = to_parameter_pins(method_type.block, closure)
    block_return_type = to_complex_type(method_type.block.type.return_type)
    Pin::Signature.new(generics: generics, parameters: block_parameters, return_type: block_return_type, source: :rbs, type_location: closure.location, closure: closure)
  end
  Pin::Signature.new(generics: generics, parameters: parameters, return_type: return_type, block: block, source: :rbs, type_location: closure.location, closure: closure)
end