Module: Docscribe::Types::RBS::TypeFormatter

Defined in:
lib/docscribe/types/rbs/type_formatter.rb

Overview

Convert RBS type objects into YARD-ish type strings.

This is intentionally best-effort formatting: YARD type syntax is simpler than RBS, so some information is collapsed or approximated.

Class Method Summary collapse

Class Method Details

.fallback_string(type) ⇒ String

Note:

module_function: defines #fallback_string (visibility: private)

Fallback conversion of an unrecognized RBS type to a cleaned string representation.

Parameters:

  • type (Docscribe::Types::RBS::TypeFormatter::rbs_type)

    the unrecognized RBS type object

Returns:

  • (String)


62
63
64
65
66
67
# File 'lib/docscribe/types/rbs/type_formatter.rb', line 62

def fallback_string(type)
  type.to_s
      .gsub(/\A::/, '')
      .gsub(/\bbool\b/, 'Boolean')
      .gsub(/\buntyped\b/, 'Object')
end

.format_anyString

Note:

module_function: defines #format_any (visibility: private)

Format RBS ‘any` type as the YARD-equivalent `Object`.

Returns:

  • (String)


115
116
117
# File 'lib/docscribe/types/rbs/type_formatter.rb', line 115

def format_any
  'Object'
end

.format_boolString

Note:

module_function: defines #format_bool (visibility: private)

Format RBS ‘bool` type as the YARD `Boolean`.

Returns:

  • (String)


123
124
125
# File 'lib/docscribe/types/rbs/type_formatter.rb', line 123

def format_bool
  'Boolean'
end

.format_bottomString

Note:

module_function: defines #format_bottom (visibility: private)

Format RBS bottom type as YARD ‘Object`.

Returns:

  • (String)


205
206
207
# File 'lib/docscribe/types/rbs/type_formatter.rb', line 205

def format_bottom
  'Object'
end

.format_class_typeString

Note:

module_function: defines #format_class_type (visibility: private)

Format RBS class type as YARD ‘Class`.

Returns:

  • (String)


229
230
231
# File 'lib/docscribe/types/rbs/type_formatter.rb', line 229

def format_class_type
  'Class'
end

.format_generic_args(name, args, collapse_generics:, collapse_object_generics:) ⇒ String

Note:

module_function: defines #format_generic_args (visibility: private)

Format generic type arguments for a named type.

Parameters:

  • name (String)

    the type name

  • args (Array<Docscribe::Types::RBS::TypeFormatter::rbs_type>)

    the generic type arguments

  • collapse_generics (Boolean)

    whether to omit generic type arguments

  • collapse_object_generics (Boolean)

    whether to collapse generics when all inner types are Object

Returns:

  • (String)


311
312
313
314
315
316
317
318
319
320
# File 'lib/docscribe/types/rbs/type_formatter.rb', line 311

def format_generic_args(name, args, collapse_generics:, collapse_object_generics:)
  return name if collapse_generics

  formatted = args.map do |a|
    to_yard(a, collapse_generics: collapse_generics, collapse_object_generics: collapse_object_generics)
  end
  return name if collapse_object_generics && formatted.all? { |s| s == 'Object' }

  "#{name}<#{formatted.join(', ')}>"
end

.format_instanceString

Note:

module_function: defines #format_instance (visibility: private)

Format RBS instance type as YARD ‘Object`.

Returns:

  • (String)


221
222
223
# File 'lib/docscribe/types/rbs/type_formatter.rb', line 221

def format_instance
  'Object'
end

.format_intersection(type, collapse_generics:, collapse_object_generics:) ⇒ String

Note:

module_function: defines #format_intersection (visibility: private)

Format an RBS Intersection type as ‘Type & Type` list.

Parameters:

  • type (RBS::Types::Intersection)

    the intersection type

  • collapse_generics (Boolean)

    whether to omit generic type arguments

  • collapse_object_generics (Boolean)

    collapse Object generics flag

Returns:

  • (String)


263
264
265
266
267
# File 'lib/docscribe/types/rbs/type_formatter.rb', line 263

def format_intersection(type, collapse_generics:, collapse_object_generics:)
  type.types.map do |t|
    to_yard(t, collapse_generics: collapse_generics, collapse_object_generics: collapse_object_generics)
  end.join(' & ')
end

.format_literal(lit) ⇒ String

Note:

module_function: defines #format_literal (visibility: private)

Map a Ruby literal value to its corresponding YARD type name.

Parameters:

  • lit (RBS::Types::Literal)

    a Ruby literal value

Returns:

  • (String)


160
161
162
163
164
165
166
167
168
169
170
# File 'lib/docscribe/types/rbs/type_formatter.rb', line 160

def format_literal(lit)
  case lit
  when Integer then 'Integer'
  when Float   then 'Float'
  when String  then 'String'
  when Symbol  then 'Symbol'
  when TrueClass, FalseClass then 'Boolean'
  when NilClass then 'nil'
  else 'Object'
  end
end

.format_named(type, collapse_generics:, collapse_object_generics:) ⇒ String

Note:

module_function: defines #format_named (visibility: private)

Format an RBS named type (class, interface, alias) with optional generic arguments.

Parameters:

  • type (Docscribe::Types::RBS::TypeFormatter::named_rbs_type)

    the unrecognized RBS type object

  • collapse_generics (Boolean)

    whether to omit generic type arguments

  • collapse_object_generics (Boolean)

    whether to collapse generics when all inner types are Object

Returns:

  • (String)


291
292
293
294
295
296
297
298
299
300
301
# File 'lib/docscribe/types/rbs/type_formatter.rb', line 291

def format_named(type, collapse_generics:, collapse_object_generics:)
  name = type.name.to_s.delete_prefix('::')
  args = type.respond_to?(:args) ? type.args : [] #: Array[untyped]

  if args && !args.empty?
    format_generic_args(name, args, collapse_generics: collapse_generics,
                                    collapse_object_generics: collapse_object_generics)
  else
    name
  end
end

.format_nilString

Note:

module_function: defines #format_nil (visibility: private)

Format RBS ‘nil` type as the YARD `nil`.

Returns:

  • (String)


139
140
141
# File 'lib/docscribe/types/rbs/type_formatter.rb', line 139

def format_nil
  'nil'
end

.format_optional(type, collapse_generics:, collapse_object_generics:) ⇒ String

Note:

module_function: defines #format_optional (visibility: private)

Format an RBS Optional type as a YARD optional type with ‘?` suffix.

Parameters:

  • type (RBS::Types::Optional)

    the optional type to format

  • collapse_generics (Boolean)

    whether to omit generic type arguments

  • collapse_object_generics (Boolean)

    collapse Object generics flag

Returns:

  • (String)


150
151
152
153
# File 'lib/docscribe/types/rbs/type_formatter.rb', line 150

def format_optional(type, collapse_generics:, collapse_object_generics:)
  "#{to_yard(type.type, collapse_generics: collapse_generics,
                        collapse_object_generics: collapse_object_generics)}?"
end

.format_procString

Note:

module_function: defines #format_proc (visibility: private)

Format RBS Proc type as the YARD ‘Proc`.

Returns:

  • (String)


176
177
178
# File 'lib/docscribe/types/rbs/type_formatter.rb', line 176

def format_proc
  'Proc'
end

.format_record(type, collapse_generics:, collapse_object_generics:) ⇒ String

Note:

module_function: defines #format_record (visibility: private)

Format an RBS Record type as a YARD ‘Hash<Symbol, ValueType>`.

Parameters:

  • type (RBS::Types::Record)

    the record type

  • collapse_generics (Boolean)

    whether to omit generic type arguments

  • collapse_object_generics (Boolean)

    collapse Object generics flag

Returns:

  • (String)


249
250
251
252
253
254
# File 'lib/docscribe/types/rbs/type_formatter.rb', line 249

def format_record(type, collapse_generics:, collapse_object_generics:)
  value_types = type.all_fields.values.map do |(ty, _)|
    to_yard(ty, collapse_generics: collapse_generics, collapse_object_generics: collapse_object_generics)
  end.uniq
  "Hash<Symbol, #{value_types.join(', ')}>"
end

.format_selfString

Note:

module_function: defines #format_self (visibility: private)

Format RBS self type as YARD ‘self`.

Returns:

  • (String)


213
214
215
# File 'lib/docscribe/types/rbs/type_formatter.rb', line 213

def format_self
  'self'
end

.format_topString

Note:

module_function: defines #format_top (visibility: private)

Format RBS top type as YARD ‘Object`.

Returns:

  • (String)


197
198
199
# File 'lib/docscribe/types/rbs/type_formatter.rb', line 197

def format_top
  'Object'
end

.format_tuple(type, collapse_generics:, collapse_object_generics:) ⇒ String

Note:

module_function: defines #format_tuple (visibility: private)

Format an RBS Tuple type as a parenthesized list of YARD types.

Parameters:

  • type (RBS::Types::Tuple)

    the tuple type to format

  • collapse_generics (Boolean)

    whether to omit generic type arguments

  • collapse_object_generics (Boolean)

    collapse Object generics flag

Returns:

  • (String)


187
188
189
190
191
# File 'lib/docscribe/types/rbs/type_formatter.rb', line 187

def format_tuple(type, collapse_generics:, collapse_object_generics:)
  "(#{type.types.map do |t|
    to_yard(t, collapse_generics: collapse_generics, collapse_object_generics: collapse_object_generics)
  end.join(', ')})"
end

.format_union(type, collapse_generics:, collapse_object_generics:) ⇒ String

Note:

module_function: defines #format_union (visibility: private)

Format an RBS Union type as a comma-separated list of YARD types.

Parameters:

  • type (RBS::Types::Union)

    the union type to format

  • collapse_generics (Boolean)

    whether to omit generic type arguments

  • collapse_object_generics (Boolean)

    collapse Object generics flag

Returns:

  • (String)


276
277
278
279
280
281
282
# File 'lib/docscribe/types/rbs/type_formatter.rb', line 276

def format_union(type, collapse_generics:, collapse_object_generics:)
  type.types.map do |t|
    to_yard(t, collapse_generics: collapse_generics, collapse_object_generics: collapse_object_generics)
  end
            .uniq
            .join(', ')
end

.format_variable(type) ⇒ String

Note:

module_function: defines #format_variable (visibility: private)

Format an RBS type variable as its name string.

Parameters:

  • type (RBS::Types::Variable)

    the variable type

Returns:

  • (String)


238
239
240
# File 'lib/docscribe/types/rbs/type_formatter.rb', line 238

def format_variable(type)
  type.name.to_s
end

.format_voidString

Note:

module_function: defines #format_void (visibility: private)

Format RBS ‘void` type as the YARD `void`.

Returns:

  • (String)


131
132
133
# File 'lib/docscribe/types/rbs/type_formatter.rb', line 131

def format_void
  'void'
end

.formatter_pairsHash<Class, Docscribe::Types::RBS::TypeFormatter::formatter_fn>

Note:

module_function: defines #formatter_pairs (visibility: private)

Hash of RBS type classes and their YARD formatter lambdas.

Returns:

  • (Hash<Class, Docscribe::Types::RBS::TypeFormatter::formatter_fn>)


81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/docscribe/types/rbs/type_formatter.rb', line 81

def formatter_pairs # steep:ignore # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
  @formatter_pairs ||= {
    ::RBS::Types::Bases::Any => ->(_, **) { format_any },
    ::RBS::Types::Bases::Bool => ->(_, **) { format_bool },
    ::RBS::Types::Bases::Void => ->(_, **) { format_void },
    ::RBS::Types::Bases::Nil => ->(_, **) { format_nil },
    ::RBS::Types::Optional => lambda { |t, cg:, cog:|
      format_optional(t, collapse_generics: cg, collapse_object_generics: cog)
    },
    ::RBS::Types::Union => lambda { |t, cg:, cog:|
      format_union(t, collapse_generics: cg, collapse_object_generics: cog)
    },
    ::RBS::Types::Literal => ->(t, **) { format_literal(t.literal) },
    ::RBS::Types::Proc => ->(_, **) { format_proc },
    ::RBS::Types::Tuple => lambda { |t, cg:, cog:|
      format_tuple(t, collapse_generics: cg, collapse_object_generics: cog)
    },
    ::RBS::Types::Bases::Top => ->(_, **) { format_top },
    ::RBS::Types::Bases::Bottom => ->(_, **) { format_bottom },
    ::RBS::Types::Bases::Self => ->(_, **) { format_self },
    ::RBS::Types::Bases::Instance => ->(_, **) { format_instance },
    ::RBS::Types::Bases::Class => ->(_, **) { format_class_type },
    ::RBS::Types::Variable => ->(t, **) { format_variable(t) },
    ::RBS::Types::Record => lambda { |t, cg:, cog:|
      format_record(t, collapse_generics: cg, collapse_object_generics: cog)
    },
    ::RBS::Types::Intersection => ->(t, cg:, cog:) { format_intersection(t, collapse_generics: cg, collapse_object_generics: cog) }
  }.freeze
end

.literal_to_yard(lit) ⇒ String

Note:

module_function: defines #literal_to_yard (visibility: private)

Convert a Ruby literal value to its YARD type name string.

Parameters:

  • lit (Object)

    a Ruby literal value

Returns:

  • (String)


327
328
329
330
331
332
333
334
335
336
337
# File 'lib/docscribe/types/rbs/type_formatter.rb', line 327

def literal_to_yard(lit)
  case lit
  when Integer then 'Integer'
  when Float   then 'Float'
  when String  then 'String'
  when Symbol  then 'Symbol'
  when TrueClass, FalseClass then 'Boolean'
  when NilClass then 'nil'
  else 'Object'
  end
end

.named_type?(type) ⇒ Boolean

Note:

module_function: defines #named_type? (visibility: private)

Check if the given type object is a named RBS type (class, singleton, interface, or alias).

Parameters:

  • type (Docscribe::Types::RBS::TypeFormatter::rbs_type)

    the RBS type object to check

Returns:

  • (Boolean)


40
41
42
# File 'lib/docscribe/types/rbs/type_formatter.rb', line 40

def named_type?(type)
  named_type_classes.any? { |klass| type.is_a?(klass) }
end

.named_type_classesArray<Class>

Note:

module_function: defines #named_type_classes (visibility: private)

Return or memoize the list of RBS type classes considered named types.

Returns:

  • (Array<Class>)


48
49
50
51
52
53
54
55
# File 'lib/docscribe/types/rbs/type_formatter.rb', line 48

def named_type_classes
  @named_type_classes ||= [
    ::RBS::Types::ClassInstance,
    ::RBS::Types::ClassSingleton,
    ::RBS::Types::Interface,
    ::RBS::Types::Alias
  ].freeze
end

.to_yard(type, collapse_generics: false, collapse_object_generics: false) ⇒ String

Note:

module_function: defines #to_yard (visibility: private)

Dispatch an RBS type object to the appropriate YARD formatter.

Parameters:

  • type (Docscribe::Types::RBS::TypeFormatter::rbs_type, nil)

    the RBS type object to convert

  • collapse_generics (Boolean) (defaults to: false)

    whether to omit generic type arguments

  • collapse_object_generics (Boolean) (defaults to: false)

    whether to collapse generics when all inner types are Object

Returns:

  • (String)


20
21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/docscribe/types/rbs/type_formatter.rb', line 20

def to_yard(type, collapse_generics: false, collapse_object_generics: false)
  return 'Object' unless type

  handler = to_yard_formatters.find { |klass, _| type.is_a?(klass) }
  return handler.last.call(type, cg: collapse_generics, cog: collapse_object_generics) if handler

  if named_type?(type)
    return format_named(type, # steep:ignore
                        collapse_generics: collapse_generics,
                        collapse_object_generics: collapse_object_generics)
  end

  fallback_string(type)
end

.to_yard_formattersHash<Class, Docscribe::Types::RBS::TypeFormatter::formatter_fn>

Note:

module_function: defines #to_yard_formatters (visibility: private)

Return or memoize the dispatch hash mapping RBS type classes to formatter lambdas.

Returns:

  • (Hash<Class, Docscribe::Types::RBS::TypeFormatter::formatter_fn>)


73
74
75
# File 'lib/docscribe/types/rbs/type_formatter.rb', line 73

def to_yard_formatters
  @to_yard_formatters ||= formatter_pairs.to_h.freeze
end