Module: Docscribe::Infer

Defined in:
lib/docscribe/infer.rb,
lib/docscribe/infer/names.rb,
lib/docscribe/infer/params.rb,
lib/docscribe/infer/raises.rb,
lib/docscribe/infer/returns.rb,
lib/docscribe/infer/ast_walk.rb,
lib/docscribe/infer/behavior.rb,
lib/docscribe/infer/literals.rb,
lib/docscribe/infer/constants.rb

Overview

Best-effort inference utilities used to generate YARD tags.

This module is intentionally heuristic:

  • it aims to be useful for common Ruby patterns

  • it prefers safe fallback behavior when uncertain

  • when inference cannot be specific, it falls back to ‘Object`

External signature sources such as RBS and Sorbet are applied later in the doc builder and can override these inferred types.

Defined Under Namespace

Modules: ASTWalk, Behavior, Literals, Names, Params, Raises, Returns

Constant Summary collapse

FALLBACK_TYPE =

Default fallback type used when inference cannot be certain.

'Object'
DEFAULT_ERROR =

Ruby’s implicit rescue target for bare ‘rescue`.

'StandardError'
LITERAL_TYPE_MAP =

Node type to literal type name mapping.

{
  int: 'Integer',
  float: 'Float',
  str: 'String',
  dstr: 'String',
  sym: 'Symbol',
  true: 'Boolean',
  false: 'Boolean',
  nil: 'nil',
  array: 'Array',
  hash: 'Hash',
  regexp: 'Regexp'
}.freeze

Class Method Summary collapse

Class Method Details

.analyze_behavior(node, method_name) ⇒ Hash<Symbol, Boolean>

Analyze method behavior from AST node and method name.

Parameters:

  • node (Parser::AST::Node?) —

    def or defs node

  • method_name (Symbol?)

Returns:

  • (Hash<Symbol, Boolean>)


46
47
48
49
# File 'lib/docscribe/infer.rb', line 46

def analyze_behavior(node, method_name)
  body = extract_body(node)
  Behavior.analyze(body, method_name)
end

.const_full_name(node) ⇒ String?

Convert a constant AST node into its fully qualified name.

Parameters:

  • node (Parser::AST::Node, nil) —

    constant AST node to resolve

Returns:

  • (String, nil)


167
168
169
# File 'lib/docscribe/infer.rb', line 167

def const_full_name(node)
  Names.const_full_name(node)
end

.extract_body(node) ⇒ Parser::AST::Node?

Extract method body from def/defs node.

Parameters:

  • node (Parser::AST::Node) —

    def or defs node

Returns:

  • (Parser::AST::Node?)


68
69
70
71
72
73
# File 'lib/docscribe/infer.rb', line 68

def extract_body(node)
  return nil unless node.is_a?(Parser::AST::Node)

  body_idx = node.type == :def ? 2 : 3
  node.children[body_idx]
end

.infer_behavior_description(node, method_name) ⇒ String?

Get behavioral description for a method.

Parameters:

  • node (Hash<Symbol, Boolean>) —

    def or defs node

  • method_name (Symbol?)

Returns:

  • (String?)


56
57
58
59
60
61
62
# File 'lib/docscribe/infer.rb', line 56

def infer_behavior_description(node, method_name)
  body = extract_body(node)
  return nil unless body

  analysis = Behavior.analyze(body, method_name)
  Behavior.infer_description(analysis, method_name)
end

.infer_param_type(name, default_str, fallback_type: FALLBACK_TYPE, treat_options_keyword_as_hash: true) ⇒ String

Infer a parameter type from its internal name form and optional default expression.

The internal parameter name may include:

  • ‘*` for rest args

  • ‘**` for keyword rest args

  • ‘&` for block args

  • trailing ‘:` for keyword args

Parameters:

  • name (String) —

    internal parameter name representation

  • default_str (String?) —

    source for the default expression

  • fallback_type (String) (defaults to: FALLBACK_TYPE) —

    default type when uncertain

  • treat_options_keyword_as_hash (Boolean) (defaults to: true) —

    treat options: as Hash

Returns:

  • (String)


89
90
91
92
93
94
95
96
# File 'lib/docscribe/infer.rb', line 89

def infer_param_type(name, default_str, fallback_type: FALLBACK_TYPE, treat_options_keyword_as_hash: true)
  Params.infer_param_type(
    name,
    default_str,
    fallback_type: fallback_type,
    treat_options_keyword_as_hash: treat_options_keyword_as_hash
  )
end

.infer_raises_from_node(node) ⇒ Array<String>

Infer exception classes raised or rescued within an AST node.

Parameters:

  • node (Parser::AST::Node) —

    constant AST node to resolve

Returns:

  • (Array<String>)


37
38
39
# File 'lib/docscribe/infer.rb', line 37

def infer_raises_from_node(node)
  Raises.infer_raises_from_node(node)
end

.infer_return_type(method_source) ⇒ String

Infer a return type from full method source.

Parameters:

  • method_source (String?) —

    method definition source

Returns:

  • (String)


110
111
112
# File 'lib/docscribe/infer.rb', line 110

def infer_return_type(method_source)
  Returns.infer_return_type(method_source)
end

.infer_return_type_from_node(node) ⇒ String

Infer a return type from an already parsed ‘:def` / `:defs` node.

Parameters:

  • node (Parser::AST::Node) —

    constant AST node to resolve

Returns:

  • (String)


118
119
120
# File 'lib/docscribe/infer.rb', line 118

def infer_return_type_from_node(node)
  Returns.infer_return_type_from_node(node)
end

.last_expr_type(node, fallback_type: FALLBACK_TYPE, nil_as_optional: true) ⇒ String?

Infer the type of the last expression in an AST node.

Parameters:

  • node (Parser::AST::Node, nil) —

    constant AST node to resolve

  • fallback_type (String) (defaults to: FALLBACK_TYPE) —

    default type when uncertain

  • nil_as_optional (Boolean) (defaults to: true) —

    render nil as optional

Returns:

  • (String, nil)


155
156
157
158
159
160
161
# File 'lib/docscribe/infer.rb', line 155

def last_expr_type(node, fallback_type: FALLBACK_TYPE, nil_as_optional: true)
  Returns.last_expr_type(
    node,
    fallback_type: fallback_type,
    nil_as_optional: nil_as_optional
  )
end

.parse_expr(src) ⇒ Parser::AST::Node?

Parse a standalone expression source string for inference helpers.

Parameters:

  • src (String?) —

    expression source to parse

Returns:

  • (Parser::AST::Node, nil)


102
103
104
# File 'lib/docscribe/infer.rb', line 102

def parse_expr(src)
  Params.parse_expr(src)
end

.returns_spec_from_node(node, fallback_type: FALLBACK_TYPE, nil_as_optional: true, core_rbs_provider: nil, param_types: nil, container: nil, signature_provider: nil) ⇒ Hash<Symbol, String, Array<(Array<String>, String)>>

Return structured normal/rescue return information for a method node.

Result shape:

  • ‘:normal` => the normal return type

  • ‘:rescues` => rescue-branch conditional return info

Parameters:

  • node (Parser::AST::Node) —

    constant AST node to resolve

  • fallback_type (String) (defaults to: FALLBACK_TYPE) —

    default type when uncertain

  • nil_as_optional (Boolean) (defaults to: true) —

    render nil as optional

  • core_rbs_provider (Docscribe::Types::RBS::Provider?) (defaults to: nil) —

    core RBS type lookup provider

  • param_types (Hash<String, String>?) (defaults to: nil) —

    parameter name -> type map

  • container (String?) (defaults to: nil)
  • signature_provider (Docscribe::Types::ProviderChain?) (defaults to: nil)

Returns:

  • (Hash<Symbol, String, Array<(Array<String>, String)>>)


136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/docscribe/infer.rb', line 136

def returns_spec_from_node(node, fallback_type: FALLBACK_TYPE, nil_as_optional: true, core_rbs_provider: nil, # rubocop:disable Metrics/ParameterLists
                           param_types: nil, container: nil, signature_provider: nil)
  Returns.returns_spec_from_node(
    node,
    fallback_type: fallback_type,
    nil_as_optional: nil_as_optional,
    core_rbs_provider: core_rbs_provider,
    param_types: param_types,
    container: container,
    signature_provider: signature_provider
  )
end

.type_from_literal(node, fallback_type: FALLBACK_TYPE) ⇒ String

Infer a YARD-ish type string from a literal AST node.

Parameters:

  • node (Parser::AST::Node, nil) —

    constant AST node to resolve

  • fallback_type (String) (defaults to: FALLBACK_TYPE) —

    default type when uncertain

Returns:

  • (String)


176
177
178
# File 'lib/docscribe/infer.rb', line 176

def type_from_literal(node, fallback_type: FALLBACK_TYPE)
  Literals.type_from_literal(node, fallback_type: fallback_type)
end

.unify_types(type_a, type_b, fallback_type: FALLBACK_TYPE, nil_as_optional: true) ⇒ String

Unify two inferred type strings conservatively.

Parameters:

  • type_a (String, nil) —

    first type to unify

  • type_b (String, nil) —

    second type to unify

  • fallback_type (String) (defaults to: FALLBACK_TYPE) —

    default type when uncertain

  • nil_as_optional (Boolean) (defaults to: true) —

    render nil as optional

Returns:

  • (String)


187
188
189
190
191
192
193
194
# File 'lib/docscribe/infer.rb', line 187

def unify_types(type_a, type_b, fallback_type: FALLBACK_TYPE, nil_as_optional: true)
  Returns.unify_types(
    type_a,
    type_b,
    fallback_type: fallback_type,
    nil_as_optional: nil_as_optional
  )
end