Class: YARDSorbet::Handlers::SigHandler

Inherits:
YARD::Handlers::Ruby::Base
  • Object
show all
Extended by:
T::Sig
Defined in:
lib/yard-sorbet/handlers/sig_handler.rb

Overview

A YARD Handler for Sorbet type declarations

Constant Summary collapse

Documentable =

YARD types that can have docstrings attached to them

T.type_alias do
  T.any(
    YARD::CodeObjects::MethodObject, YARD::Parser::Ruby::MethodCallNode, YARD::Parser::Ruby::MethodDefinitionNode
  )
end

Instance Method Summary collapse

Instance Method Details

#document_attrs(method_objects) ⇒ void (private)

This method returns an undefined value.

Parameters:

  • method_objects (Array<YARD::CodeObjects::MethodObject>)


73
# File 'lib/yard-sorbet/handlers/sig_handler.rb', line 73

def document_attrs(method_objects) =  method_objects.each { parse_node(_1, _1.docstring, include_params: false) }

#merged_into_attr?(attr_node) ⇒ Boolean (private)

An attr* sig can be merged into a previous attr* docstring if it is the only parameter passed to the attr* declaration. This is to avoid needing to rewrite the source code to separate merged and unmerged attr* declarations.

Parameters:

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

Returns:

  • (Boolean)


60
61
62
63
64
65
66
67
68
69
70
# File 'lib/yard-sorbet/handlers/sig_handler.rb', line 60

def merged_into_attr?(attr_node)
  names = NodeUtils.validated_attribute_names(attr_node)
  return false if names.size != 1

  attrs = namespace.attributes[scope][names[0]]
  return false if attrs.nil? || attrs.empty?

  document_attrs(attrs.values.compact)
  attr_node.docstring = nil
  true
end

#parse_node(attach_to, docstring, include_params: true) ⇒ void (private)

This method returns an undefined value.

Parameters:

  • attach_to (Documentable)
  • docstring (String, nil)
  • include_params (Boolean) (defaults to: true)


76
77
78
79
80
81
82
# File 'lib/yard-sorbet/handlers/sig_handler.rb', line 76

def parse_node(attach_to, docstring, include_params: true)
  existing_docstring = docstring.is_a?(YARD::Docstring)
  docstring, directives = Directives.extract_directives(docstring) unless existing_docstring
  parse_sig(docstring, include_params:)
  attach_to.docstring = docstring.to_raw
  Directives.add_directives(attach_to.docstring, directives) unless existing_docstring
end

#parse_params(node, docstring) ⇒ void (private)

This method returns an undefined value.

Parameters:

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


97
98
99
100
101
102
103
104
# File 'lib/yard-sorbet/handlers/sig_handler.rb', line 97

def parse_params(node, docstring)
  sibling = NodeUtils.sibling_node(node)
  sibling[0][0].each do |param|
    param_name = param[0][0]
    types = SigToYARD.convert(param.last)
    TagUtils.upsert_tag(docstring, 'param', types, param_name)
  end
end

#parse_return(node, docstring) ⇒ void (private)

This method returns an undefined value.

Parameters:

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


107
108
109
110
# File 'lib/yard-sorbet/handlers/sig_handler.rb', line 107

def parse_return(node, docstring)
  type = SigToYARD.convert(NodeUtils.sibling_node(node))
  TagUtils.upsert_tag(docstring, 'return', type)
end

#parse_sig(docstring, include_params: true) ⇒ void (private)

This method returns an undefined value.

Parameters:

  • docstring (YARD::Docstring)
  • include_params (Boolean) (defaults to: true)


85
86
87
88
89
90
91
92
93
94
# File 'lib/yard-sorbet/handlers/sig_handler.rb', line 85

def parse_sig(docstring, include_params: true)
  NodeUtils.bfs_traverse(statement) do |node|
    case node.source
    when 'returns' then parse_return(node, docstring)
    when 'params' then parse_params(node, docstring) if include_params
    when 'void' then TagUtils.upsert_tag(docstring, 'return', TagUtils::VOID_RETURN_TYPE)
    when 'abstract' then TagUtils.upsert_tag(docstring, 'abstract')
    end
  end
end

#processvoid

This method returns an undefined value.

Swap the method definition docstring and the sig docstring. Parse relevant parts of the sig and include them as well.



24
25
26
27
28
29
30
31
# File 'lib/yard-sorbet/handlers/sig_handler.rb', line 24

def process
  method_node = NodeUtils.get_method_node(NodeUtils.sibling_node(statement))
  case method_node
  when YARD::Parser::Ruby::MethodDefinitionNode then process_def(method_node)
  when YARD::Parser::Ruby::MethodCallNode then process_attr(method_node)
  end
  statement.docstring = nil
end

#process_attr(attr_node) ⇒ void (private)

This method returns an undefined value.

Parameters:

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


50
51
52
53
54
# File 'lib/yard-sorbet/handlers/sig_handler.rb', line 50

def process_attr(attr_node)
  return if merged_into_attr?(attr_node)

  parse_node(attr_node, statement.docstring, include_params: false)
end

#process_def(def_node) ⇒ void (private)

This method returns an undefined value.

Parameters:

  • def_node (YARD::Parser::Ruby::MethodDefinitionNode)


36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/yard-sorbet/handlers/sig_handler.rb', line 36

def process_def(def_node)
  separator = scope == :instance && def_node.type == :def ? '#' : '.'
  registered = YARD::Registry.at("#{namespace}#{separator}#{def_node.method_name(true)}")
  if registered
    parse_node(registered, statement.docstring || registered.docstring)
    # Since we're probably in an RBI file, delete the def node, which could otherwise erroneously override the
    # visibility setting
    NodeUtils.delete_node(def_node)
  else
    parse_node(def_node, statement.docstring)
  end
end