Module: YARDSorbet::SigToYARD

Extended by:
T::Sig
Defined in:
lib/yard-sorbet/sig_to_yard.rb

Overview

Translate sig type syntax to YARD type syntax.

Class Method Summary collapse

Class Method Details

.build_generic_type(node) ⇒ String (private)

Parameters:

  • node (YARD::Parser::Ruby::AstNode)

Returns:

  • (String)


44
45
46
47
48
49
50
51
# File 'lib/yard-sorbet/sig_to_yard.rb', line 44

private_class_method def self.build_generic_type(node)
  return node.source if node.empty? || node.type != :aref

  collection_type = node.first.source
  member_type = node.last.children.map { |child| build_generic_type(child) }.join(', ')

  "#{collection_type}[#{member_type}]"
end

.convert(node) ⇒ Array<String>

Parameters:

  • node (YARD::Parser::Ruby::AstNode)

Returns:

  • (Array<String>)

See Also:



11
12
13
14
# File 'lib/yard-sorbet/sig_to_yard.rb', line 11

def self.convert(node)
  # scrub newlines, as they break the YARD parser
  convert_node(node).map { |type| type.gsub(/\n\s*/, ' ') }
end

.convert_aref(node) ⇒ Array<String> (private)

Parameters:

  • node (YARD::Parser::Ruby::AstNode)

Returns:

  • (Array<String>)


54
55
56
57
58
59
60
61
62
63
# File 'lib/yard-sorbet/sig_to_yard.rb', line 54

private_class_method def self.convert_aref(node)
  # https://www.rubydoc.info/gems/yard/file/docs/Tags.md#Parametrized_Types
  case node.first.source
  when 'T::Array', 'T::Enumerable', 'T::Range', 'T::Set' then convert_collection(node)
  when 'T::Hash' then convert_hash(node)
  else
    log.info("Unsupported sig aref node #{node.source}")
    [build_generic_type(node)]
  end
end

.convert_array(node) ⇒ Array<String> (private)

Parameters:

  • node (YARD::Parser::Ruby::AstNode)

Returns:

  • (Array<String>)


66
67
68
69
70
71
# File 'lib/yard-sorbet/sig_to_yard.rb', line 66

private_class_method def self.convert_array(node)
  # https://www.rubydoc.info/gems/yard/file/docs/Tags.md#Order-Dependent_Lists
  member_types = node.first.children.map { |n| convert_node(n) }
  sequence = member_types.map { |mt| mt.size == 1 ? mt[0] : mt.to_s.tr('"', '') }.join(', ')
  ["Array(#{sequence})"]
end

.convert_call(node) ⇒ Array<String> (private)

Parameters:

  • node (YARD::Parser::Ruby::MethodCallNode)

Returns:

  • (Array<String>)


74
75
76
# File 'lib/yard-sorbet/sig_to_yard.rb', line 74

private_class_method def self.convert_call(node)
  node.namespace.source == 'T' ? convert_t_method(node) : [node.source]
end

.convert_collection(node) ⇒ Array<String> (private)

Parameters:

  • node (YARD::Parser::Ruby::AstNode)

Returns:

  • (Array<String>)


79
80
81
82
83
# File 'lib/yard-sorbet/sig_to_yard.rb', line 79

private_class_method def self.convert_collection(node)
  collection_type = node.first.source.split('::').last
  member_type = convert_node(node.last.first).join(', ')
  ["#{collection_type}<#{member_type}>"]
end

.convert_hash(node) ⇒ Array<String> (private)

Parameters:

  • node (YARD::Parser::Ruby::AstNode)

Returns:

  • (Array<String>)


86
87
88
89
90
91
# File 'lib/yard-sorbet/sig_to_yard.rb', line 86

private_class_method def self.convert_hash(node)
  kv = node.last.children
  key_type = convert_node(kv.first).join(', ')
  value_type = convert_node(kv.last).join(', ')
  ["Hash{#{key_type} => #{value_type}}"]
end

.convert_list(node) ⇒ Array<String> (private)

Parameters:

  • node (YARD::Parser::Ruby::AstNode)

Returns:

  • (Array<String>)


94
95
96
# File 'lib/yard-sorbet/sig_to_yard.rb', line 94

private_class_method def self.convert_list(node)
  node.children.size == 1 ? convert_node(node.children.first) : [node.source]
end

.convert_node(node) ⇒ Array<String> (private)

Parameters:

  • node (YARD::Parser::Ruby::AstNode)

Returns:

  • (Array<String>)


17
18
19
20
21
22
23
# File 'lib/yard-sorbet/sig_to_yard.rb', line 17

private_class_method def self.convert_node(node)
  case node
  when YARD::Parser::Ruby::MethodCallNode then convert_call(node)
  when YARD::Parser::Ruby::ReferenceNode then convert_ref(node)
  else convert_node_type(node)
  end
end

.convert_node_type(node) ⇒ Array<String> (private)

Parameters:

  • node (YARD::Parser::Ruby::AstNode)

Returns:

  • (Array<String>)


26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/yard-sorbet/sig_to_yard.rb', line 26

private_class_method def self.convert_node_type(node)
  case node.type
  when :aref then convert_aref(node)
  when :arg_paren then convert_node(node.first)
  when :array then convert_array(node)
  # Fixed hashes as return values are unsupported:
  # https://github.com/lsegal/yard/issues/425
  #
  # Hash key params can be individually documented with `@option`, but
  # sig translation is currently unsupported.
  when :hash then ['Hash']
  # seen when sig methods omit parentheses
  when :list then convert_list(node)
  else convert_unknown(node)
  end
end

.convert_ref(node) ⇒ Array<String> (private)

Parameters:

  • node (YARD::Parser::Ruby::AstNode)

Returns:

  • (Array<String>)


99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/yard-sorbet/sig_to_yard.rb', line 99

private_class_method def self.convert_ref(node)
  source = node.source
  case source
  when 'T::Boolean' then ['Boolean'] # YARD convention for booleans
  # YARD convention is use singleton objects when applicable:
  # https://www.rubydoc.info/gems/yard/file/docs/Tags.md#Literals
  when 'FalseClass' then ['false']
  when 'NilClass' then ['nil']
  when 'TrueClass' then ['true']
  else [source]
  end
end

.convert_t_method(node) ⇒ Array<String> (private)

Parameters:

  • node (YARD::Parser::Ruby::MethodCallNode)

Returns:

  • (Array<String>)


113
114
115
116
117
118
119
120
121
122
# File 'lib/yard-sorbet/sig_to_yard.rb', line 113

private_class_method def self.convert_t_method(node)
  case node.method_name(true)
  when :any then node.last.first.children.map { |n| convert_node(n) }.flatten
  # Order matters here, putting `nil` last results in a more concise
  # return syntax in the UI (superscripted `?`)
  # https://github.com/lsegal/yard/blob/cfa62ae/lib/yard/templates/helpers/html_helper.rb#L499-L500
  when :nilable then convert_node(node.last) + ['nil']
  else [node.source]
  end
end

.convert_unknown(node) ⇒ Array<String> (private)

Parameters:

  • node (YARD::Parser::Ruby::AstNode)

Returns:

  • (Array<String>)


125
126
127
128
# File 'lib/yard-sorbet/sig_to_yard.rb', line 125

private_class_method def self.convert_unknown(node)
  log.warn("Unsupported sig #{node.type} node #{node.source}")
  [node.source]
end