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, Object>

Analyze method behavior from AST node and method name.

Parameters:

  • node (Object)

    def or defs node

  • method_name (Object)

Returns:

  • (Hash<Symbol, Object>)


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) ⇒ Object?

Extract method body from def/defs node.

Parameters:

  • node (Object)

    def or defs node

Returns:

  • (Object?)


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 (Object)

    def or defs node

  • method_name (Object)

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