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: when included, also defines #fallback_string (instance visibility: private)

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

Parameters:

  • type (::RBS::Type)

    the unrecognized RBS type object

Returns:

  • (String)


191
192
193
194
195
196
# File 'lib/docscribe/types/rbs/type_formatter.rb', line 191

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

.format_anyString

Note:

module_function: when included, also defines #format_any (instance visibility: private)

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

Returns:

  • (String)


36
37
38
# File 'lib/docscribe/types/rbs/type_formatter.rb', line 36

def format_any
  'Object'
end

.format_boolString

Note:

module_function: when included, also defines #format_bool (instance visibility: private)

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

Returns:

  • (String)


44
45
46
# File 'lib/docscribe/types/rbs/type_formatter.rb', line 44

def format_bool
  'Boolean'
end

.format_literal(lit) ⇒ String

Note:

module_function: when included, also defines #format_literal (instance visibility: private)

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

Parameters:

  • lit (Object)

    a Ruby literal value

Returns:

  • (String)


79
80
81
82
83
84
85
86
87
88
89
# File 'lib/docscribe/types/rbs/type_formatter.rb', line 79

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:) ⇒ String

Note:

module_function: when included, also defines #format_named (instance visibility: private)

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

Parameters:

  • type (::RBS::Types::ClassInstance, ::RBS::Types::Interface, ::RBS::Types::Alias)
  • collapse_generics (Boolean)

    whether to omit generic type arguments

Returns:

  • (String)


117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/docscribe/types/rbs/type_formatter.rb', line 117

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

  if args && !args.empty?
    return name if collapse_generics

    "#{name}<#{args.map { |a| to_yard(a, collapse_generics: collapse_generics) }.join(', ')}>"
  else
    name
  end
end

.format_nilString

Note:

module_function: when included, also defines #format_nil (instance visibility: private)

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

Returns:

  • (String)


60
61
62
# File 'lib/docscribe/types/rbs/type_formatter.rb', line 60

def format_nil
  'nil'
end

.format_optional(type, collapse_generics:) ⇒ String

Note:

module_function: when included, also defines #format_optional (instance 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

Returns:

  • (String)


70
71
72
# File 'lib/docscribe/types/rbs/type_formatter.rb', line 70

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

.format_procString

Note:

module_function: when included, also defines #format_proc (instance visibility: private)

Format RBS Proc type as the YARD ‘Proc`.

Returns:

  • (String)


95
96
97
# File 'lib/docscribe/types/rbs/type_formatter.rb', line 95

def format_proc
  'Proc'
end

.format_union(type, collapse_generics:) ⇒ String

Note:

module_function: when included, also defines #format_union (instance 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

Returns:

  • (String)


105
106
107
108
109
# File 'lib/docscribe/types/rbs/type_formatter.rb', line 105

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

.format_voidString

Note:

module_function: when included, also defines #format_void (instance visibility: private)

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

Returns:

  • (String)


52
53
54
# File 'lib/docscribe/types/rbs/type_formatter.rb', line 52

def format_void
  'void'
end

.literal_to_yard(lit) ⇒ String

Note:

module_function: when included, also defines #literal_to_yard (instance visibility: private)

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

Parameters:

  • lit (Object)

    a Ruby literal value

Returns:

  • (String)


135
136
137
138
139
140
141
142
143
144
145
# File 'lib/docscribe/types/rbs/type_formatter.rb', line 135

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: when included, also defines #named_type? (instance visibility: private)

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

Parameters:

  • type (::RBS::Type)

    the RBS type object to check

Returns:

  • (Boolean)


169
170
171
# File 'lib/docscribe/types/rbs/type_formatter.rb', line 169

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

.named_type_classesArray<Class>

Note:

module_function: when included, also defines #named_type_classes (instance visibility: private)

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

Returns:

  • (Array<Class>)


177
178
179
180
181
182
183
184
# File 'lib/docscribe/types/rbs/type_formatter.rb', line 177

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) ⇒ String

Note:

module_function: when included, also defines #to_yard (instance visibility: private)

Dispatch an RBS type object to the appropriate YARD formatter.

Parameters:

  • type (::RBS::Type)

    the RBS type object to convert

  • collapse_generics (Boolean) (defaults to: false)

    whether to omit generic type arguments

Returns:

  • (String)


153
154
155
156
157
158
159
160
161
162
# File 'lib/docscribe/types/rbs/type_formatter.rb', line 153

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

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

  return format_named(type, collapse_generics: collapse_generics) if named_type?(type)

  fallback_string(type)
end

.to_yard_formattersHash{Class=>Proc}

Note:

module_function: when included, also defines #to_yard_formatters (instance visibility: private)

rubocop:disable Metrics/AbcSize, Layout/LineLength Return or memoize the dispatch hash mapping RBS type classes to formatter lambdas.

Returns:

  • (Hash{Class=>Proc})


18
19
20
21
22
23
24
25
26
27
28
29
# File 'lib/docscribe/types/rbs/type_formatter.rb', line 18

def to_yard_formatters
  @to_yard_formatters ||= {
    ::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 => ->(t, collapse_generics:) { format_optional(t, collapse_generics: collapse_generics) },
    ::RBS::Types::Union => ->(t, collapse_generics:) { format_union(t, collapse_generics: collapse_generics) },
    ::RBS::Types::Literal => ->(t, **) { format_literal(t.literal) },
    ::RBS::Types::Proc => ->(_, **) { format_proc }
  }.freeze
end