Module: Docscribe::InlineRewriter::DocBuilder

Defined in:
lib/docscribe/inline_rewriter/doc_builder.rb

Overview

Build generated YARD-style doc lines for methods and attribute helpers.

DocBuilder combines:

  • Ruby visibility/container metadata from Collector

  • optional external signatures from Sorbet/RBS providers

  • fallback AST inference from Docscribe::Infer

It is responsible for producing complete doc blocks for aggressive mode and “missing lines only” payloads for safe merge mode.

Constant Summary collapse

PARAM_TYPE_COLLECTORS =
{
  arg: lambda { |arg_node, param_types, external_sig, config|
    collect_param_type(
      arg_node,
      param_types,
      external_sig,
      config,
      infer_name: nil
    )
  },

  optarg: lambda { |arg_node, param_types, external_sig, config|
    collect_optarg_param_type(
      arg_node,
      param_types,
      external_sig,
      config,
      infer_name: nil
    )
  },

  kwarg: lambda { |arg_node, param_types, external_sig, config|
    collect_param_type(
      arg_node,
      param_types,
      external_sig,
      config,
      infer_name: ->(param_name) { "#{param_name}:" }
    )
  },

  kwoptarg: lambda { |arg_node, param_types, external_sig, config|
    collect_optarg_param_type(
      arg_node,
      param_types,
      external_sig,
      config,
      infer_name: ->(param_name) { "#{param_name}:" }
    )
  }
}.freeze
ARG_DEFAULT_NAMES =
{ restarg: 'args', kwrestarg: 'kwargs', blockarg: 'block' }.freeze

Class Method Summary collapse

Class Method Details

.add_missing_private(lines, reasons, ctx) ⇒ void

Note:

module_function: defines #add_missing_private (visibility: private)

This method returns an undefined value.

Add missing private

Parameters:

  • lines (Array<String>)

    array of output doc lines being accumulated

  • reasons (Array<Hash<Symbol, Object>>)

    array of reason hashes for –explain output

  • ctx (Hash<Symbol, Object>)

    merged context hash with info and indent



931
932
933
934
935
936
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 931

def add_missing_private(lines, reasons, ctx)
  return unless ctx[:visibility] == :private && !ctx[:info][:has_private]

  lines << "#{ctx[:indent]}# @private\n"
  reasons << { type: :missing_visibility, message: 'missing @private' }
end

.add_missing_protected(lines, reasons, ctx) ⇒ void

Note:

module_function: defines #add_missing_protected (visibility: private)

This method returns an undefined value.

Add missing protected

Parameters:

  • lines (Array<String>)

    array of output doc lines being accumulated

  • reasons (Array<Hash<Symbol, Object>>)

    array of reason hashes for –explain output

  • ctx (Hash<Symbol, Object>)

    merged context hash with info and indent



945
946
947
948
949
950
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 945

def add_missing_protected(lines, reasons, ctx)
  return unless ctx[:visibility] == :protected && !ctx[:info][:has_protected]

  lines << "#{ctx[:indent]}# @protected\n"
  reasons << { type: :missing_visibility, message: 'missing @protected' }
end

.append_assemble_body_lines(line_ary, indent, setup, ctx) ⇒ void

Note:

module_function: defines #append_assemble_body_lines (visibility: private)

This method returns an undefined value.

Append assemble body lines

Parameters:

  • line_ary (Array<String>)

    output line array

  • indent (String)

    indentation string for doc comment lines

  • setup (Hash<Symbol, Object>)

    method setup hash with name, types, scope

  • ctx (Hash<Symbol, Object>)

    merged context hash with info and indent



1123
1124
1125
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1123

def append_assemble_body_lines(line_ary, indent, setup, ctx)
  line_ary.concat(build_all_body_tags(indent, setup, ctx))
end

.append_merge_tag_lines(line_ary, ctx) ⇒ void

Note:

module_function: defines #append_merge_tag_lines (visibility: private)

This method returns an undefined value.

Append merge tag lines

Parameters:

  • line_ary (Array<String>)

    output line array

  • ctx (Hash<Symbol, Object>)

    merged context hash with info and indent



451
452
453
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 451

def append_merge_tag_lines(line_ary, ctx)
  line_ary.concat(build_all_merge_tags(ctx))
end

.append_note_continuation(line, info) ⇒ Object

Note:

module_function: defines #append_note_continuation (visibility: private)

Append note continuation lines

Parameters:

  • line (String)

    doc comment line

  • info (Hash<Symbol, Object>)

    parse info hash

Returns:

  • (Object)


359
360
361
362
363
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 359

def append_note_continuation(line, info)
  return unless info[:last_tag] == :note && info[:note_lines].any?

  info[:note_lines].last << line.chomp
end

.append_option_lines(lines, default, indent, pname, fallback_type) ⇒ void

Note:

module_function: defines #append_option_lines (visibility: private)

This method returns an undefined value.

Append option lines

Parameters:

  • lines (Array<String>)

    array of output doc lines being accumulated

  • default (Parser::AST::Node)

    default value node

  • indent (String)

    indentation string for the doc line

  • pname (String)

    the parameter name to look up

  • fallback_type (String)

    default type string when inference fails



1623
1624
1625
1626
1627
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1623

def append_option_lines(lines, default, indent, pname, fallback_type)
  hash_option_pairs(default).each do |pair|
    lines << build_option_line(pair, indent, pname, fallback_type)
  end
end

.append_param_doc(line, doc, indent) ⇒ String

Note:

module_function: defines #append_param_doc (visibility: private)

Append param doc text

Parameters:

  • line (String)

    existing param tag line

  • doc (String)

    documentation text

  • indent (String)

    indentation string

Returns:

  • (String)


1607
1608
1609
1610
1611
1612
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1607

def append_param_doc(line, doc, indent)
  parts = doc.split("\n")
  result = +"#{line} #{parts.first}"
  parts[1..]&.each { |l| result << "\n#{indent}#   #{l}" }
  result
end

.append_tag_continuation(content, info) ⇒ void

Note:

module_function: defines #append_tag_continuation (visibility: private)

This method returns an undefined value.

Append continuation to current tag

Parameters:

  • content (String)

    tag continuation text

  • info (Hash<Symbol, Object>)

    parse info hash



615
616
617
618
619
620
621
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 615

def append_tag_continuation(content, info)
  text = content.strip
  return if text.empty?

  append_to_return_description(text, info) if info[:last_tag] == :return
  append_to_param_description(text, info) if info[:last_tag] == :param
end

.append_to_param_description(text, info) ⇒ void

Note:

module_function: defines #append_to_param_description (visibility: private)

This method returns an undefined value.

Append text to param description

Parameters:

  • text (String)

    text to append

  • info (Hash<Symbol, Object>)

    parse info hash



643
644
645
646
647
648
649
650
651
652
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 643

def append_to_param_description(text, info)
  pname = info[:last_param]
  return unless pname

  if info[:param_descriptions][pname]
    info[:param_descriptions][pname] += "\n#{text}"
  else
    info[:param_descriptions][pname] = text
  end
end

.append_to_return_description(text, info) ⇒ void

Note:

module_function: defines #append_to_return_description (visibility: private)

This method returns an undefined value.

Append text to return description

Parameters:

  • text (String)

    text to append

  • info (Hash<Symbol, Object>)

    parse info hash



629
630
631
632
633
634
635
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 629

def append_to_return_description(text, info)
  if info[:return_description]
    info[:return_description] += "\n#{text}"
  else
    info[:return_description] = text
  end
end

.assemble_doc_lines(indent, setup, **ctx) ⇒ Array<String>

Note:

module_function: defines #assemble_doc_lines (visibility: private)

Assemble doc lines

Parameters:

  • indent (String)

    indent

  • setup (Hash<Symbol, Object>)

    setup

  • ctx (Object)

    context hash with config, insertion, params_lines, raise_types, override_tags

Returns:

  • (Array<String>)


1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1103

def assemble_doc_lines(indent, setup, **ctx)
  line_ary = build_header_lines(
    indent,
    config: ctx[:config],
    container: setup[:container], method_symbol: setup[:method_symbol], name: setup[:name],
    normal_type: setup[:normal_type]
  )

  append_assemble_body_lines(line_ary, indent, setup, ctx)
  line_ary
end

.build(insertion, config:, **opts) ⇒ String?

Note:

module_function: defines #build (visibility: private)

Build

Parameters:

  • insertion (Object)

    the collected method insertion object

  • config (Docscribe::Config)

    Docscribe configuration object

  • opts (Object)

    additional keyword options forwarded to doc_setup

Returns:

  • (String, nil)

    if StandardError

  • (nil)

    if StandardError

Raises:

  • (StandardError)


72
73
74
75
76
77
78
79
80
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 72

def build(insertion, config:, **opts)
  setup = doc_setup(insertion, config: config, **opts)
  return nil unless setup

  build_unsafe(insertion, config: config, setup: setup, **opts)
rescue StandardError => e
  debug_warn(e, insertion: insertion, name: '(unknown)', phase: 'DocBuilder.build')
  nil
end

.build_all_body_tags(indent, setup, ctx) ⇒ Array<String>

Note:

module_function: defines #build_all_body_tags (visibility: private)

Build all body tags

Parameters:

  • indent (String)

    indentation string for doc comment lines

  • setup (Hash<Symbol, Object>)

    method setup hash with name, types, scope

  • ctx (Hash<Symbol, Object>)

    merged context hash with info and indent

Returns:

  • (Array<String>)


1134
1135
1136
1137
1138
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1134

def build_all_body_tags(indent, setup, ctx)
  result = core_body_tags(indent, setup, ctx)
  result.insert(4, ctx[:params_lines]) if ctx[:params_lines]
  result.flatten
end

.build_all_merge_tags(ctx) ⇒ Array<String>

Note:

module_function: defines #build_all_merge_tags (visibility: private)

Build all merge tags

Parameters:

  • ctx (Hash<Symbol, Object>)

    merged context hash with info and indent

Returns:

  • (Array<String>)


460
461
462
463
464
465
466
467
468
469
470
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 460

def build_all_merge_tags(ctx)
  i = ctx[:i]
  s = ctx[:s]
  c = ctx[:config]
  info = ctx[:info]
  [merge_visibility_tag_lines(i, s[:visibility], c, info),
   merge_module_function_note_lines(i, ctx[:insertion], s[:name], info),
   merge_param_lines(s[:node], i, config: c, external_sig: s[:external_sig],
                                  param_types: ctx[:param_types], info: info),
   merge_raise_tag_lines(s[:node], i, c, info)].flatten
end

.build_all_param_lines(args, indent, config, external_sig: nil, **kwargs) ⇒ Array<String>?

Note:

module_function: defines #build_all_param_lines (visibility: private)

Build all param lines

Parameters:

  • args (Parser::AST::Node)

    arguments AST node

  • indent (String)

    indentation string for the doc line

  • config (Docscribe::Config)

    Docscribe configuration object

  • external_sig (Docscribe::Types::MethodSignature, nil) (defaults to: nil)

    external method signature for type overrides

  • kwargs (Object)

    additional keyword args including insertion, params_lines, raise_types, override_tags

Returns:

  • (Array<String>, nil)


1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1055

def build_all_param_lines(args, indent, config, external_sig: nil, **kwargs)
  param_lines = [] #: Array[String]
  params = (args.children || []).each_with_object(param_lines) do |a, p|
    p.concat(build_param_line(a, indent, external_sig, kwargs[:param_types_override],
                              skip_anonymous_block_params: config.skip_anonymous_block_params?,
                              fallback_type: config.fallback_type,
                              treat_options_keyword_as_hash: config.treat_options_keyword_as_hash?,
                              param_documentation: param_doc_for_arg(a, kwargs, config),
                              param_tag_style: config.param_tag_style))
  end
  params.empty? ? nil : params
end

.build_arg_line(arg_node, indent, external_sig, param_types_override, **opts) ⇒ String

Note:

module_function: defines #build_arg_line (visibility: private)

Build arg line

Parameters:

  • arg_node (Parser::AST::Node)

    AST node for the required argument

  • indent (String)

    indentation string for doc comment lines

  • external_sig (Docscribe::Types::MethodSignature, nil)

    external method signature for type overrides

  • param_types_override (Hash<String, String>, nil)

    map of parameter name to override type

  • opts (Object)

    additional options for param formatting

Returns:

  • (String)


1375
1376
1377
1378
1379
1380
1381
1382
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1375

def build_arg_line(arg_node, indent, external_sig, param_types_override, **opts)
  pname = arg_node.children.first.to_s
  ty = lookup_param_type(external_sig, param_types_override, pname, pname,
                         infer_default: nil,
                         fallback_type: opts[:fallback_type],
                         treat_options_keyword_as_hash: opts[:treat_options_keyword_as_hash])
  format_param_tag(indent, pname, ty, opts[:param_documentation], style: opts[:param_tag_style])
end

.build_blockarg_line(arg_node, indent, external_sig, param_types_override, **opts) ⇒ String

Note:

module_function: defines #build_blockarg_line (visibility: private)

Build blockarg line

Parameters:

  • arg_node (Parser::AST::Node)

    AST node for the block argument (&block)

  • indent (String)

    indentation string for doc comment lines

  • external_sig (Docscribe::Types::MethodSignature, nil)

    external method signature for type overrides

  • param_types_override (Hash<String, String>, nil)

    map of parameter name to override type

  • opts (Object)

    additional options for param formatting

Returns:

  • (String)


1526
1527
1528
1529
1530
1531
1532
1533
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1526

def build_blockarg_line(arg_node, indent, external_sig, param_types_override, **opts)
  pname = (arg_node.children.first || 'block').to_s
  ty = lookup_param_type(external_sig, param_types_override, pname, "&#{pname}",
                         infer_default: nil,
                         fallback_type: opts[:fallback_type],
                         treat_options_keyword_as_hash: opts[:treat_options_keyword_as_hash])
  format_param_tag(indent, pname, ty, opts[:param_documentation], style: opts[:param_tag_style])
end

.build_debug_location(insertion, name) ⇒ String

Note:

module_function: defines #build_debug_location (visibility: private)

Build debug location

Parameters:

  • insertion (Object)

    the collected method insertion object

  • name (String)

    the method name string

Returns:

  • (String)


1945
1946
1947
1948
1949
1950
1951
1952
1953
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1945

def build_debug_location(insertion, name)
  return name.to_s unless insertion

  expr = insertion.node.loc.expression
  buf = expr.source_buffer.name
  sym = insertion.scope == :class ? '.' : '#'
  ctr = insertion.container || 'Object'
  +"#{buf}:#{expr.line} #{ctr}#{sym}#{name}"
end

.build_default_msg_lines(indent, config, scope, visibility, description: nil) ⇒ Array<String>

Note:

module_function: defines #build_default_msg_lines (visibility: private)

Build default msg lines

Parameters:

  • indent (String)

    indentation string for the doc line

  • config (Docscribe::Config)

    Docscribe configuration object

  • scope (Symbol)

    method scope symbol

  • visibility (Symbol)

    method visibility symbol

  • description (Array<String>, nil) (defaults to: nil)

    optional description lines

Returns:

  • (Array<String>)


1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1260

def build_default_msg_lines(indent, config, scope, visibility, description: nil)
  if description&.any?
    result = description.map { |line| line.empty? ? "#{indent}#" : "#{indent}# #{line}" }
    result << "#{indent}#" unless result.last == "#{indent}#"
    result
  elsif config.include_default_message?
    ["#{indent}# #{config.default_message(scope, visibility)}", "#{indent}#"]
  else
    []
  end
end

.build_doc_lines(setup, config:, **kwargs) ⇒ Array<String>

Note:

module_function: defines #build_doc_lines (visibility: private)

Build doc lines

Parameters:

  • setup (Hash<Symbol, Object>)

    method setup hash with indent, name, types, scope

  • config (Docscribe::Config)

    Docscribe configuration object

  • kwargs (Object)

    additional keyword args including insertion, params_lines, raise_types, override_tags

Returns:

  • (Array<String>)


1087
1088
1089
1090
1091
1092
1093
1094
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1087

def build_doc_lines(setup, config:, **kwargs)
  i = setup[:indent]
  assemble_doc_lines(i, setup, config: config, insertion: kwargs[:insertion],
                               params_lines: kwargs[:params_lines],
                               raise_types: kwargs[:raise_types], override_tags: kwargs[:override_tags],
                               return_description: kwargs[:return_description],
                               description: kwargs[:description])
end

.build_header_lines(indent, config:, **opts) ⇒ Array<String>

Note:

module_function: defines #build_header_lines (visibility: private)

Build header lines

Parameters:

  • indent (String)

    indentation string for the doc line

  • config (Docscribe::Config)

    Docscribe configuration object

  • opts (Object)

    additional options including container, method_symbol, name, normal_type

Returns:

  • (Array<String>)


1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1239

def build_header_lines(indent, config:, **opts)
  if config.emit_header?
    c = opts[:container]
    ms = opts[:method_symbol]
    n = opts[:name]
    nt = opts[:normal_type]
    ["#{indent}# +#{c}#{ms}#{n}+ -> #{nt}", "#{indent}#"]
  else
    []
  end
end

.build_initial_line_ary(existing_lines, indent) ⇒ Array<String>

Note:

module_function: defines #build_initial_line_ary (visibility: private)

Build initial line ary

Parameters:

  • existing_lines (Array<String>)

    existing doc comment lines being merged

  • indent (String)

    indentation string for the doc line

Returns:

  • (Array<String>)


417
418
419
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 417

def build_initial_line_ary(existing_lines, indent)
  existing_lines.any? && existing_lines.last.strip != '#' ? ["#{indent}#"] : []
end

.build_kwarg_line(arg_node, indent, external_sig, param_types_override, **opts) ⇒ String

Note:

module_function: defines #build_kwarg_line (visibility: private)

Build kwarg line

Parameters:

  • arg_node (Parser::AST::Node)

    AST node for the keyword argument

  • indent (String)

    indentation string for doc comment lines

  • external_sig (Docscribe::Types::MethodSignature, nil)

    external method signature for type overrides

  • param_types_override (Hash<String, String>, nil)

    map of parameter name to override type

  • opts (Object)

    additional options for param formatting

Returns:

  • (String)


1449
1450
1451
1452
1453
1454
1455
1456
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1449

def build_kwarg_line(arg_node, indent, external_sig, param_types_override, **opts)
  pname = arg_node.children.first.to_s
  ty = lookup_param_type(external_sig, param_types_override, pname, "#{pname}:",
                         infer_default: nil,
                         fallback_type: opts[:fallback_type],
                         treat_options_keyword_as_hash: opts[:treat_options_keyword_as_hash])
  format_param_tag(indent, pname, ty, opts[:param_documentation], style: opts[:param_tag_style])
end

.build_kwoptarg_line(arg_node, indent, external_sig, param_types_override, **opts) ⇒ String

Note:

module_function: defines #build_kwoptarg_line (visibility: private)

Build kwoptarg line

Parameters:

  • arg_node (Parser::AST::Node)

    AST node for the optional keyword argument

  • indent (String)

    indentation string for doc comment lines

  • external_sig (Docscribe::Types::MethodSignature, nil)

    external method signature for type overrides

  • param_types_override (Hash<String, String>, nil)

    map of parameter name to override type

  • opts (Object)

    additional options for param formatting

Returns:

  • (String)


1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1467

def build_kwoptarg_line(arg_node, indent, external_sig, param_types_override, **opts)
  pname, default = *arg_node
  pname = pname.to_s
  default_loc = default&.loc
  default_src = default_loc&.expression&.source
  ty = lookup_param_type(external_sig, param_types_override, pname, "#{pname}:",
                         infer_default: default_src,
                         fallback_type: opts[:fallback_type],
                         treat_options_keyword_as_hash: opts[:treat_options_keyword_as_hash])
  format_param_tag(indent, pname, ty, opts[:param_documentation], style: opts[:param_tag_style])
end

.build_kwrestarg_line(arg_node, indent, external_sig, param_types_override, **opts) ⇒ String

Note:

module_function: defines #build_kwrestarg_line (visibility: private)

Build kwrestarg line

Parameters:

  • arg_node (Parser::AST::Node)

    AST node for the keyword rest argument (**kwargs)

  • indent (String)

    indentation string for doc comment lines

  • external_sig (Docscribe::Types::MethodSignature, nil)

    external method signature for type overrides

  • param_types_override (Hash<String, String>, nil)

    map of parameter name to override type

  • opts (Object)

    additional options for param formatting

Returns:

  • (String)


1509
1510
1511
1512
1513
1514
1515
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1509

def build_kwrestarg_line(arg_node, indent, external_sig, param_types_override, **opts)
  pname = (arg_node.children.first || 'kwargs').to_s
  ty = external_sig&.rest_keywords&.type ||
       lookup_param_type_by_infer(param_types_override, pname, "**#{pname}",
                                  opts[:fallback_type], opts[:treat_options_keyword_as_hash])
  format_param_tag(indent, pname, ty, opts[:param_documentation], style: opts[:param_tag_style])
end

.build_merge_additions(insertion, existing_lines:, config:, **options) ⇒ String?

Note:

module_function: defines #build_merge_additions (visibility: private)

Build merge additions

Parameters:

  • insertion (Object)

    the collected method insertion object

  • existing_lines (Array<String>)

    existing doc comment lines being merged

  • config (Docscribe::Config)

    Docscribe configuration object

  • options (Object)

    additional keyword options forwarded to downstream methods

Returns:

  • (String, nil)

    if StandardError

  • (nil)

    if StandardError

Raises:

  • (StandardError)


92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 92

def build_merge_additions(insertion, existing_lines:, config:, **options)
  setup = doc_setup(insertion, config: config, **options)
  return '' unless setup

  info = parse_existing_doc_tags(existing_lines)
  merge_dest_lines(existing_lines, setup: setup, insertion: insertion, config: config, info: info,
                                   param_types: options[:param_types])
rescue StandardError => e
  debug_warn(e, insertion: insertion, name: setup&.dig(:name) || '(unknown)',
                phase: 'DocBuilder.build_merge_additions')
  nil
end

.build_missing_merge_result(insertion, existing_lines:, config:, **options) ⇒ Hash<Symbol, Object>, Hash

Note:

module_function: defines #build_missing_merge_result (visibility: private)

Build missing merge result

Parameters:

  • insertion (Object)

    the collected method insertion object

  • existing_lines (Array<String>)

    existing doc comment lines being merged

  • config (Docscribe::Config)

    Docscribe configuration object

  • options (Object)

    additional keyword options forwarded to downstream methods

Returns:

  • (Hash<Symbol, Object>)

    if StandardError

  • (Hash)

    if StandardError

Raises:

  • (StandardError)


115
116
117
118
119
120
121
122
123
124
125
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 115

def build_missing_merge_result(insertion, existing_lines:, config:, **options)
  setup = doc_setup(insertion, config: config, **options)
  return { lines: [], reasons: [] } unless setup

  info = parse_existing_doc_tags(existing_lines)
  collect_all_missing(setup, info, insertion, config, options)
rescue StandardError => e
  debug_warn(e, insertion: insertion, name: setup&.dig(:name) || '(unknown)',
                phase: 'DocBuilder.build_missing_merge_result')
  { lines: [], reasons: [] }
end

.build_module_function_note_lines(indent, insertion, name) ⇒ Array<String>

Note:

module_function: defines #build_module_function_note_lines (visibility: private)

Build module function note lines

Parameters:

  • indent (String)

    indentation string for the doc line

  • insertion (Object)

    the collected method insertion object

  • name (String)

    the method name string

Returns:

  • (Array<String>)


1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1296

def build_module_function_note_lines(indent, insertion, name)
  return [] unless insertion.respond_to?(:module_function) && insertion.module_function

  included_vis =
    if insertion.respond_to?(:included_instance_visibility) && insertion.included_instance_visibility
      insertion.included_instance_visibility
    else
      :private
    end

  ["#{indent}# @note module_function: defines ##{name} (visibility: #{included_vis})"]
end

.build_optarg_lines(arg_node, indent, external_sig, param_types_override, **opts) ⇒ Array<String>

Note:

module_function: defines #build_optarg_lines (visibility: private)

Build optarg lines

Parameters:

  • arg_node (Parser::AST::Node)

    AST node for the optional argument

  • indent (String)

    indentation string for doc comment lines

  • external_sig (Docscribe::Types::MethodSignature, nil)

    external method signature for type overrides

  • param_types_override (Hash<String, String>, nil)

    map of parameter name to override type

  • opts (Object)

    additional options for param formatting

Returns:

  • (Array<String>)


1393
1394
1395
1396
1397
1398
1399
1400
1401
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1393

def build_optarg_lines(arg_node, indent, external_sig, param_types_override, **opts)
  pname, default = *arg_node
  pname = pname.to_s
  ty = optarg_type(pname, default, external_sig, param_types_override, opts)
  lines = [format_param_tag(indent, pname, ty, opts[:param_documentation], style: opts[:param_tag_style])]

  append_option_lines(lines, default, indent, pname, opts[:fallback_type])
  lines
end

.build_option_line(pair, indent, pname, fallback_type) ⇒ String

Note:

module_function: defines #build_option_line (visibility: private)

Build option line

Parameters:

  • pair (Parser::AST::Node)

    AST pair node containing key and value

  • indent (String)

    indentation string for the doc line

  • pname (String)

    the parent parameter name for @option scope

  • fallback_type (String)

    default type string when inference fails

Returns:

  • (String)


1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1648

def build_option_line(pair, indent, pname, fallback_type)
  key_node, value_node = pair.children
  option_key = option_key_name(key_node)
  option_type = Infer::Literals.type_from_literal(value_node, fallback_type: fallback_type)
  option_default = node_default_literal(value_node)

  line = "#{indent}# @option #{pname} [#{option_type}] :#{option_key}"
  line += " (#{option_default})" if option_default
  line += ' Description of this option.'
  line
end

.build_param_and_raise_info(setup, config, opts) ⇒ (Hash<String, String>, nil, Array<String>, nil, Array<String>)

Note:

module_function: defines #build_param_and_raise_info (visibility: private)

Build param and raise info

Parameters:

  • setup (Hash<Symbol, Object>)

    method setup hash with name, normal_type, scope, visibility

  • config (Docscribe::Config)

    Docscribe configuration object

  • opts (Hash<Symbol, Object>)

    additional options including

Returns:

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


167
168
169
170
171
172
173
174
175
176
177
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 167

def build_param_and_raise_info(setup, config, opts)
  pt = opts[:param_types] || build_param_types_from_node(setup[:node], external_sig: setup[:external_sig],
                                                                       config: config)
  pl = if config.emit_param_tags?
         build_params_lines(setup[:node], setup[:indent], external_sig: setup[:external_sig], config: config,
                                                          param_types_override: pt,
                                                          param_descriptions: opts[:param_descriptions])
       end
  rt = config.emit_raise_tags? ? Docscribe::Infer.infer_raises_from_node(setup[:node]) : [] #: Array[String]
  [pt, pl, rt]
end

.build_param_line(arg_node, indent, external_sig, param_types_override, **opts) ⇒ Array<String>

Note:

module_function: defines #build_param_line (visibility: private)

Build param line

Parameters:

  • arg_node (Parser::AST::Node)

    AST node for the argument

  • indent (String)

    indentation string for doc comment lines

  • external_sig (Docscribe::Types::MethodSignature, nil)

    external method signature for type overrides

  • param_types_override (Hash<String, String>, nil)

    map of parameter name to override type

  • opts (Object)

    additional options for param formatting (fallback_type, param_tag_style, etc.)

Returns:

  • (Array<String>)


1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1216

def build_param_line(arg_node, indent, external_sig, param_types_override, **opts)
  method_name = :"build_#{arg_node.type}_line"
  if respond_to?(method_name, true)
    return [] if arg_node.type == :blockarg && opts[:skip_anonymous_block_params] && arg_node.children.first.nil?

    return [send(method_name, arg_node, indent, external_sig, param_types_override, **opts)]
  end

  method_name = :"build_#{arg_node.type}_lines"
  if respond_to?(method_name, true)
    return send(method_name, arg_node, indent, external_sig, param_types_override, **opts)
  end

  []
end

.build_param_tag_base(indent, name, type, style) ⇒ String

Note:

module_function: defines #build_param_tag_base (visibility: private)

Build param tag base string

Parameters:

  • indent (String)

    indentation string

  • name (String)

    parameter name

  • type (String)

    parameter type string

  • style (String, Symbol)

    tag style symbol

Returns:

  • (String)


1593
1594
1595
1596
1597
1598
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1593

def build_param_tag_base(indent, name, type, style)
  case style.to_s
  when 'name_type' then "#{indent}# @param #{name} [#{type}]"
  else "#{indent}# @param [#{type}] #{name}"
  end
end

.build_param_types_from_node(node, external_sig:, config:) ⇒ Hash<String, String>?

Note:

module_function: defines #build_param_types_from_node (visibility: private)

Build param types from node

Parameters:

Returns:

  • (Hash<String, String>, nil)


725
726
727
728
729
730
731
732
733
734
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 725

def build_param_types_from_node(node, external_sig:, config:)
  return unless node

  args = extract_args_from_node(node)
  return unless args

  param_types = {} #: Hash[String, String]
  collect_all_param_types(args, param_types, external_sig, config)
  param_types.empty? ? nil : param_types
end

.build_params_lines(node, indent, external_sig:, config:, **kwargs) ⇒ Array<String>?

Note:

module_function: defines #build_params_lines (visibility: private)

Build params lines

Parameters:

  • node (Parser::AST::Node)

    AST node whose source text to extract

  • indent (String)

    indentation string for the doc line

  • external_sig (Docscribe::Types::MethodSignature, nil)

    external method signature for type overrides

  • config (Docscribe::Config)

    Docscribe configuration object

  • kwargs (Hash)

    additional keyword args including insertion, params_lines, raise_types, override_tags

Returns:

  • (Array<String>, nil)


1039
1040
1041
1042
1043
1044
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1039

def build_params_lines(node, indent, external_sig:, config:, **kwargs)
  args = extract_args_from_node(node)
  return nil unless args

  build_all_param_lines(args, indent, config, external_sig: external_sig, **kwargs)
end

.build_plugin_context(insertion, normal_type:) ⇒ Object

Note:

module_function: defines #build_plugin_context (visibility: private)

Build plugin context

Parameters:

  • insertion (Object)

    the collected method insertion object

  • normal_type (String)

    resolved return type

Returns:

  • (Object)


1969
1970
1971
1972
1973
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1969

def build_plugin_context(insertion, normal_type:)
  node = insertion.node
  source = safe_node_source(node)
  new_plugin_context(insertion, node, source, normal_type)
end

.build_plugin_tag_lines(insertion, indent, normal_type, override_tags) ⇒ Array<String>

Note:

module_function: defines #build_plugin_tag_lines (visibility: private)

Build plugin tag lines

Parameters:

  • insertion (Object)

    the collected method insertion object

  • indent (String)

    indentation string for the doc line

  • normal_type (String)

    resolved return type

  • override_tags (Array<Object>, nil)

    plugin tag overrides

Returns:

  • (Array<String>)


1360
1361
1362
1363
1364
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1360

def build_plugin_tag_lines(insertion, indent, normal_type, override_tags)
  plugin_tags = Docscribe::Plugin.run_tag_plugins(build_plugin_context(insertion, normal_type: normal_type))
  plugin_tags.concat(Array(override_tags)) if override_tags
  render_plugin_tags(plugin_tags, indent)
end

.build_raise_tag_lines(indent, raise_types, config) ⇒ Array<String>

Note:

module_function: defines #build_raise_tag_lines (visibility: private)

Build raise tag lines

Parameters:

  • indent (String)

    indentation string for the doc line

  • raise_types (Array<String>)

    hash tracking existing @raise types

  • config (Docscribe::Config)

    Docscribe configuration object

Returns:

  • (Array<String>)


1316
1317
1318
1319
1320
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1316

def build_raise_tag_lines(indent, raise_types, config)
  return [] unless config.emit_raise_tags?

  raise_types.map { |rt| "#{indent}# @raise [#{rt}]" }
end

.build_rescue_return_lines(indent, rescue_specs, config) ⇒ Array<String>

Note:

module_function: defines #build_rescue_return_lines (visibility: private)

Build rescue return lines

Parameters:

  • indent (String)

    indentation string for the doc line

  • rescue_specs (Array<(Array<String>, String)>)

    rescue type specs

  • config (Docscribe::Config)

    Docscribe configuration object

Returns:

  • (Array<String>)


1344
1345
1346
1347
1348
1349
1350
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1344

def build_rescue_return_lines(indent, rescue_specs, config)
  return [] unless config.emit_rescue_conditional_returns?

  rescue_specs.map do |exceptions, rtype|
    "#{indent}# @return [#{rtype}] if #{exceptions.join(', ')}"
  end
end

.build_restarg_line(arg_node, indent, external_sig, param_types_override, **opts) ⇒ String

Note:

module_function: defines #build_restarg_line (visibility: private)

Build restarg line

Parameters:

  • arg_node (Parser::AST::Node)

    AST node for the rest argument (*args)

  • indent (String)

    indentation string for doc comment lines

  • external_sig (Docscribe::Types::MethodSignature, nil)

    external method signature for type overrides

  • param_types_override (Hash<String, String>, nil)

    map of parameter name to override type

  • opts (Object)

    additional options for param formatting

Returns:

  • (String)


1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1488

def build_restarg_line(arg_node, indent, external_sig, param_types_override, **opts)
  pname = (arg_node.children.first || 'args').to_s
  rest_pos = external_sig&.rest_positional
  ty = if rest_pos&.element_type
         "Array<#{rest_pos.element_type}>"
       else
         lookup_param_type_by_infer(param_types_override, pname, "*#{pname}",
                                    opts[:fallback_type], opts[:treat_options_keyword_as_hash])
       end
  format_param_tag(indent, pname, ty, opts[:param_documentation], style: opts[:param_tag_style])
end

.build_return_line_if_needed(indent, setup, config, ctx) ⇒ Array<String>

Note:

module_function: defines #build_return_line_if_needed (visibility: private)

Build return line if needed

Parameters:

  • indent (String)

    indentation string for doc comment lines

  • setup (Hash<Symbol, Object>)

    method setup hash with name, normal_type, scope, visibility

  • config (Docscribe::Config)

    Docscribe configuration object

  • ctx (Hash<Symbol, Object>)

    merged context hash with info and indent

Returns:

  • (Array<String>)


1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1184

def build_return_line_if_needed(indent, setup, config, ctx)
  ret_line = build_return_tag_line(indent, setup[:normal_type], config, setup[:scope], setup[:visibility])
  rd = ctx[:return_description]
  if ret_line && rd && !rd.empty?
    lines = rd.split("\n")
    ret_line = +"#{ret_line} #{lines.first}"
    lines[1..]&.each { |l| ret_line << "\n#{indent}#   #{l}" }
  end
  ret_line ? [ret_line] : []
end

.build_return_tag_line(indent, normal_type, config, scope, visibility) ⇒ String?

Note:

module_function: defines #build_return_tag_line (visibility: private)

Build return tag line

Parameters:

  • indent (String)

    indentation string for the doc line

  • normal_type (String)

    resolved return type

  • config (Docscribe::Config)

    Docscribe configuration object

  • scope (Symbol)

    method scope symbol

  • visibility (Symbol)

    method visibility symbol

Returns:

  • (String, nil)


1331
1332
1333
1334
1335
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1331

def build_return_tag_line(indent, normal_type, config, scope, visibility)
  return unless config.emit_return_tag?(scope, visibility)

  "#{indent}# @return [#{normal_type}]"
end

.build_unsafe(insertion, config:, setup:, **opts) ⇒ String

Note:

module_function: defines #build_unsafe (visibility: private)

Build unsafe

Parameters:

  • insertion (Object)

    the collected method insertion object

  • config (Docscribe::Config)

    Docscribe configuration object

  • setup (Hash<Symbol, Object>)

    method setup hash with name, normal_type, scope, visibility

  • opts (Object)

    additional options including infer_default, fallback_type, treat_options_keyword_as_hash

Returns:

  • (String)


151
152
153
154
155
156
157
158
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 151

def build_unsafe(insertion, config:, setup:, **opts)
  _, pl, rt = build_param_and_raise_info(setup, config, opts)
  lines = build_doc_lines(setup, config: config, insertion: insertion, params_lines: pl, raise_types: rt,
                                 override_tags: opts[:override_tags],
                                 return_description: opts[:return_description],
                                 description: opts[:description])
  lines.map { |l| "#{l}\n" }.join
end

.build_visibility_tag_lines(indent, visibility, config) ⇒ Array<String>

Note:

module_function: defines #build_visibility_tag_lines (visibility: private)

Build visibility tag lines

Parameters:

  • indent (String)

    indentation string for the doc line

  • visibility (Symbol)

    method visibility symbol

  • config (Docscribe::Config)

    Docscribe configuration object

Returns:

  • (Array<String>)


1279
1280
1281
1282
1283
1284
1285
1286
1287
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1279

def build_visibility_tag_lines(indent, visibility, config)
  return [] unless config.emit_visibility_tags?

  case visibility
  when :private then ["#{indent}# @private"]
  when :protected then ["#{indent}# @protected"]
  else []
  end
end

.collect_all_missing(setup, info, insertion, config, options) ⇒ Hash<Symbol, Object>

Note:

module_function: defines #collect_all_missing (visibility: private)

Collect all missing

Parameters:

  • setup (Hash<Symbol, Object>)

    resolved setup hash with node, name, indent, types

  • info (Hash<Symbol, Object>)

    parsed existing doc tag information

  • insertion (Object)

    the collected method insertion object

  • config (Docscribe::Config)

    Docscribe configuration object

  • options (Hash<Symbol, Object>)

    additional options hash forwarded to missing collector

Returns:

  • (Hash<Symbol, Object>)


498
499
500
501
502
503
504
505
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 498

def collect_all_missing(setup, info, insertion, config, options)
  s = setup
  ctx = { node: s[:node], indent: s[:indent], config: config, external_sig: s[:external_sig],
          info: info, strategy: options[:strategy], scope: s[:scope], visibility: s[:visibility],
          normal_type: s[:normal_type], rescue_specs: s[:rescue_specs], insertion: insertion,
          param_types: options[:param_types], override_tags: options[:override_tags] }
  collect_missing_all(ctx)
end

.collect_all_param_types(args, param_types, external_sig, config) ⇒ void

Note:

module_function: defines #collect_all_param_types (visibility: private)

This method returns an undefined value.

Collect all param types

Parameters:

  • args (Parser::AST::Node)

    arguments AST node

  • param_types (Hash<String, String>)

    hash accumulating parameter name-to-type mappings

  • external_sig (Docscribe::Types::MethodSignature, nil)

    external method signature for type overrides

  • config (Docscribe::Config)

    Docscribe configuration object



744
745
746
747
748
749
750
751
752
753
754
755
756
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 744

def collect_all_param_types(args, param_types, external_sig, config)
  # Pre-seed param_types with positional (unnamed) RBS types so that
  # collectors can keep them when external_sig lacks param names.
  positional = Array(external_sig&.positional_types)
  (args.children || []).each_with_index do |a, idx|
    if (ptype = positional[idx])
      pname = a.children.first
      param_types[pname.to_s] = ptype if pname
    end
    collector = PARAM_TYPE_COLLECTORS[a.type]
    collector&.call(a, param_types, external_sig, config)
  end
end

.collect_missing_all(ctx) ⇒ Hash<Symbol, Object>

Note:

module_function: defines #collect_missing_all (visibility: private)

Collect missing all

Parameters:

  • ctx (Hash<Symbol, Object>)

    merged context hash with info and indent

Returns:

  • (Hash<Symbol, Object>)


512
513
514
515
516
517
518
519
520
521
522
523
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 512

def collect_missing_all(ctx)
  lines = [] #: Array[String]
  reasons = [] #: Array[Hash[Symbol, untyped]]
  collect_missing_visibility!(lines, reasons, **ctx)
  collect_missing_module_function_note!(lines, reasons, **ctx)
  collect_missing_params!(lines, reasons, **ctx)
  collect_missing_raises!(lines, reasons, **ctx)
  collect_missing_return!(lines, reasons, **ctx)
  collect_missing_rescue_returns!(lines, reasons, **ctx)
  collect_missing_plugin_tags!(lines, reasons, **ctx)
  { lines: lines, reasons: reasons }
end

.collect_missing_module_function_note!(lines, reasons, **ctx) ⇒ void

Note:

module_function: defines #collect_missing_module_function_note! (visibility: private)

This method returns an undefined value.

Collect missing module function note

Parameters:

  • lines (Array<String>)

    array of output doc lines being accumulated

  • reasons (Array<Hash<Symbol, Object>>)

    array of reason hashes for –explain output

  • ctx (Object)

    merged context hash with info and indent



959
960
961
962
963
964
965
966
967
968
969
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 959

def collect_missing_module_function_note!(lines, reasons, **ctx)
  insertion = ctx[:insertion]
  unless insertion.respond_to?(:module_function) && insertion.module_function &&
         !ctx[:info][:has_module_function_note]
    return
  end

  included_vis = insertion.included_instance_visibility || :private
  lines << "#{ctx[:indent]}# @note module_function: defines ##{ctx[:name]} (visibility: #{included_vis})\n"
  reasons << { type: :missing_module_function_note, message: 'missing module_function note' }
end

.collect_missing_params!(lines, reasons, **ctx) ⇒ void

Note:

module_function: defines #collect_missing_params! (visibility: private)

This method returns an undefined value.

Collect missing params

Parameters:

  • lines (Array<String>)

    array of output doc lines being accumulated

  • reasons (Array<Hash<Symbol, Object>>)

    array of reason hashes for –explain output

  • ctx (Object)

    merged context hash with info and indent



978
979
980
981
982
983
984
985
986
987
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 978

def collect_missing_params!(lines, reasons, **ctx)
  return unless ctx[:config].emit_param_tags?

  all_params = build_params_lines(ctx[:node], ctx[:indent],
                                  external_sig: ctx[:external_sig], config: ctx[:config],
                                  param_types_override: ctx[:param_types])
  return unless all_params

  all_params.each { |pl| collect_param_from_line(pl, lines, reasons, ctx) }
end

.collect_missing_plugin_tags!(lines, reasons, **ctx) ⇒ void

Note:

module_function: defines #collect_missing_plugin_tags! (visibility: private)

This method returns an undefined value.

Collect missing plugin tags

Parameters:

  • lines (Array<String>)

    array of output doc lines being accumulated

  • reasons (Array<Hash<Symbol, Object>>)

    array of reason hashes for –explain output

  • ctx (Object)

    merged context hash with info and indent



1900
1901
1902
1903
1904
1905
1906
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1900

def collect_missing_plugin_tags!(lines, reasons, **ctx)
  plugin_tags = Docscribe::Plugin.run_tag_plugins(build_plugin_context(ctx[:insertion],
                                                                       normal_type: ctx[:normal_type]))
  plugin_tags.concat(Array(ctx[:override_tags])) if ctx[:override_tags]

  plugin_tags.each { |tag| record_plugin_tag(tag, lines, reasons, ctx) }
end

.collect_missing_raises!(lines, reasons, **ctx) ⇒ void

Note:

module_function: defines #collect_missing_raises! (visibility: private)

This method returns an undefined value.

Collect missing raises

Parameters:

  • lines (Array<String>)

    array of output doc lines being accumulated

  • reasons (Array<Hash<Symbol, Object>>)

    array of reason hashes for –explain output

  • ctx (Object)

    merged context hash with info and indent



1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1809

def collect_missing_raises!(lines, reasons, **ctx)
  return unless ctx[:config].emit_raise_tags?

  inferred = Docscribe::Infer.infer_raises_from_node(ctx[:node])
  existing = ctx[:info][:raise_types] || {}
  missing = inferred.reject { |rt| existing[rt] }

  missing.each do |rt|
    lines << "#{ctx[:indent]}# @raise [#{rt}]\n"
    reasons << { type: :missing_raise, message: "missing @raise [#{rt}]", extra: { raise_type: rt } }
  end
end

.collect_missing_rescue_returns!(lines, reasons, **ctx) ⇒ void

Note:

module_function: defines #collect_missing_rescue_returns! (visibility: private)

This method returns an undefined value.

Collect missing rescue returns

Parameters:

  • lines (Array<String>)

    array of output doc lines being accumulated

  • reasons (Array<Hash<Symbol, Object>>)

    array of reason hashes for –explain output

  • ctx (Object)

    merged context hash with info and indent



1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1880

def collect_missing_rescue_returns!(lines, reasons, **ctx)
  return unless ctx[:config].emit_rescue_conditional_returns?
  return if ctx[:info][:has_return]

  ctx[:rescue_specs].each do |exceptions, rtype|
    lines << "#{ctx[:indent]}# @return [#{rtype}] if #{exceptions.join(', ')}\n"
    reasons << {
      type: :missing_return,
      message: "missing conditional @return for #{exceptions.join(', ')}"
    }
  end
end

.collect_missing_return!(lines, reasons, **ctx) ⇒ void

Note:

module_function: defines #collect_missing_return! (visibility: private)

This method returns an undefined value.

Collect missing return

Parameters:

  • lines (Array<String>)

    array of output doc lines being accumulated

  • reasons (Array<Hash<Symbol, Object>>)

    array of reason hashes for –explain output

  • ctx (Object)

    merged context hash with info and indent



1829
1830
1831
1832
1833
1834
1835
1836
1837
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1829

def collect_missing_return!(lines, reasons, **ctx)
  return unless ctx[:config].emit_return_tag?(ctx[:scope], ctx[:visibility])

  if !ctx[:info][:has_return]
    record_missing_return(lines, reasons, ctx)
  elsif return_type_changed?(ctx)
    record_updated_return(lines, reasons, ctx)
  end
end

.collect_missing_visibility!(lines, reasons, **ctx) ⇒ void

Note:

module_function: defines #collect_missing_visibility! (visibility: private)

This method returns an undefined value.

Collect missing visibility

Parameters:

  • lines (Array<String>)

    array of output doc lines being accumulated

  • reasons (Array<Hash<Symbol, Object>>)

    array of reason hashes for –explain output

  • ctx (Object)

    merged context hash with info and indent



917
918
919
920
921
922
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 917

def collect_missing_visibility!(lines, reasons, **ctx)
  return unless ctx[:config].emit_visibility_tags?

  add_missing_private(lines, reasons, ctx)
  add_missing_protected(lines, reasons, ctx)
end

.collect_optarg_param_type(arg_node, param_types, external_sig, config, infer_name:) ⇒ void

Note:

module_function: defines #collect_optarg_param_type (visibility: private)

This method returns an undefined value.

Collect optarg param type

Parameters:

  • arg_node (Parser::AST::Node)

    AST node for the optional/keyword optional argument

  • param_types (Hash<String, String>)

    hash accumulating parameter name-to-type mappings

  • external_sig (Docscribe::Types::MethodSignature, nil)

    external method signature for type overrides

  • config (Docscribe::Config)

    Docscribe configuration for fallback type options

  • infer_name (Proc, nil)

    lambda to transform parameter name for inference



787
788
789
790
791
792
793
794
795
796
797
798
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 787

def collect_optarg_param_type(arg_node, param_types, external_sig, config, infer_name:)
  pname, default = *arg_node
  pname = pname.to_s
  param_types[pname] ||= begin
    default_src = source_from_node(default)
    infer_pname = resolve_infer_name(pname, infer_name)
    external_sig&.param_types&.[](pname) ||
      Infer.infer_param_type(infer_pname, default_src,
                             fallback_type: config.fallback_type,
                             treat_options_keyword_as_hash: config.treat_options_keyword_as_hash?)
  end
end

.collect_param_from_line(param_line, lines, reasons, ctx) ⇒ void

Note:

module_function: defines #collect_param_from_line (visibility: private)

This method returns an undefined value.

Collect param from line

Parameters:

  • param_line (String)

    a single @param tag line to evaluate

  • lines (Array<String>)

    array of output doc lines being accumulated

  • reasons (Array<Hash<Symbol, Object>>)

    array of reason hashes for –explain output

  • ctx (Hash<Symbol, Object>)

    merged context hash with build parameters



997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 997

def collect_param_from_line(param_line, lines, reasons, ctx)
  pname = extract_param_name_from_param_line(param_line)
  return unless pname

  if !ctx[:info][:param_names].include?(pname)
    lines << "#{param_line}\n"
    reasons << { type: :missing_param, message: "missing @param #{pname}", extra: { param: pname } }
  elsif ctx[:external_sig] && ctx[:info][:param_types][pname]
    collect_updated_param(param_line, pname, lines, reasons, ctx)
  end
end

.collect_param_type(arg_node, param_types, external_sig, config, infer_name:) ⇒ void

Note:

module_function: defines #collect_param_type (visibility: private)

This method returns an undefined value.

Collect param type

Parameters:

  • arg_node (Parser::AST::Node)

    AST node for the required/keyword argument

  • param_types (Hash<String, String>)

    hash accumulating parameter name-to-type mappings

  • external_sig (Docscribe::Types::MethodSignature, nil)

    external method signature for type overrides

  • config (Docscribe::Config)

    Docscribe configuration for fallback type options

  • infer_name (Proc, nil)

    lambda to transform parameter name for inference



767
768
769
770
771
772
773
774
775
776
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 767

def collect_param_type(arg_node, param_types, external_sig, config, infer_name:)
  pname = arg_node.children.first.to_s
  param_types[pname] ||= begin
    infer_pname = resolve_infer_name(pname, infer_name)
    external_sig&.param_types&.[](pname) ||
      Infer.infer_param_type(infer_pname, nil,
                             fallback_type: config.fallback_type,
                             treat_options_keyword_as_hash: config.treat_options_keyword_as_hash?)
  end
end

.collect_updated_param(param_line, pname, lines, reasons, ctx) ⇒ void

Note:

module_function: defines #collect_updated_param (visibility: private)

This method returns an undefined value.

Collect updated param

Parameters:

  • param_line (String)

    a single @param tag line to evaluate

  • pname (String)

    the parameter name string

  • lines (Array<String>)

    array of output doc lines being accumulated

  • reasons (Array<Hash<Symbol, Object>>)

    array of reason hashes for –explain output

  • ctx (Hash<Symbol, Object>)

    merged context hash with build parameters



1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1018

def collect_updated_param(param_line, pname, lines, reasons, ctx)
  new_type = extract_param_type_from_param_line(param_line)
  return unless new_type && ctx[:info][:param_types][pname] != new_type

  lines << "#{param_line}\n" unless ctx[:strategy] == :safe
  reasons << {
    type: :updated_param,
    message: "updated @param #{pname} from #{ctx[:info][:param_types][pname]} to #{new_type}",
    extra: { param: pname }
  }
end

.compute_returns_spec(node, config, param_types, core_rbs_provider) ⇒ Hash<Symbol, Object>

Note:

module_function: defines #compute_returns_spec (visibility: private)

Compute returns spec

Parameters:

  • node (Parser::AST::Node)

    AST node whose source text to extract

  • config (Docscribe::Config)

    Docscribe configuration object

  • param_types (Hash<String, String>, nil)

    hash accumulating parameter name-to-type mappings

  • core_rbs_provider (Object)

    RBS type provider

Returns:

  • (Hash<Symbol, Object>)


233
234
235
236
237
238
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 233

def compute_returns_spec(node, config, param_types, core_rbs_provider)
  Docscribe::Infer.returns_spec_from_node(
    node, fallback_type: config.fallback_type, nil_as_optional: config.nil_as_optional?,
          param_types: param_types, core_rbs_provider: core_rbs_provider
  )
end

.consume_tag_or_copy(lines, idx, result) ⇒ Integer

Note:

module_function: defines #consume_tag_or_copy (visibility: private)

Consume tag line or copy verbatim

Parameters:

  • lines (Array<String>)

    doc comment lines

  • idx (Integer)

    current line index

  • result (Array<String>)

    result accumulator array

Returns:

  • (Integer)


274
275
276
277
278
279
280
281
282
283
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 274

def consume_tag_or_copy(lines, idx, result)
  if (c = lines[idx].sub(/^\s*#\s*/, '')) =~ /^@(param|return|raise)\s+\[/ && unbalanced_bracket?(c)
    buffer, consumed = join_tag_continuations(lines, idx)
    result << "# #{buffer}"
    idx + consumed
  else
    result << lines[idx]
    idx + 1
  end
end

.core_body_tags(indent, setup, ctx) ⇒ Array<Object>

Note:

module_function: defines #core_body_tags (visibility: private)

Core body tags

Parameters:

  • indent (String)

    indentation string for doc comment lines

  • setup (Hash<Symbol, Object>)

    method setup hash with name, types, scope

  • ctx (Hash<Symbol, Object>)

    merged context hash with info and indent

Returns:

  • (Array<Object>)


1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1147

def core_body_tags(indent, setup, ctx)
  config, insertion = ctx.values_at(:config, :insertion)
  [
    defaults_and_visibility(indent, config, setup[:scope], setup[:visibility], description: ctx[:description]),
    build_module_function_note_lines(indent, insertion, setup[:name]),
    ctx.dig(:info, :note_lines) || [],
    build_raise_tag_lines(indent, ctx[:raise_types], config),
    build_return_line_if_needed(indent, setup, config, ctx),
    build_rescue_return_lines(indent, setup[:rescue_specs], config),
    build_plugin_tag_lines(insertion, indent, setup[:normal_type], ctx[:override_tags])
  ]
end

.debug?Boolean

Note:

module_function: defines #debug? (visibility: private)

Debug

Returns:

  • (Boolean)


1959
1960
1961
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1959

def debug?
  ENV['DOCSCRIBE_DEBUG'] == '1'
end

.debug_warn(error, insertion:, name:, phase:) ⇒ void

Note:

module_function: defines #debug_warn (visibility: private)

This method returns an undefined value.

Debug warn

Parameters:

  • error (StandardError)

    the error that occurred

  • insertion (Object)

    the method insertion being processed

  • name (String)

    the method name

  • phase (String)

    the processing phase



1932
1933
1934
1935
1936
1937
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1932

def debug_warn(error, insertion:, name:, phase:)
  return unless debug?

  where = build_debug_location(insertion, name)
  warn "Docscribe DEBUG: #{phase} failed at #{where}: #{error.class}: #{error.message}"
end

.defaults_and_visibility(indent, config, scope, visibility, description: nil) ⇒ Array<String>

Note:

module_function: defines #defaults_and_visibility (visibility: private)

Defaults and visibility

Parameters:

  • indent (String)

    indentation string for doc comment lines

  • config (Docscribe::Config)

    Docscribe configuration object

  • scope (Symbol)

    method scope symbol

  • visibility (Symbol)

    method visibility symbol

  • description (Array<String>, nil) (defaults to: nil)

    optional description lines

Returns:

  • (Array<String>)


1169
1170
1171
1172
1173
1174
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1169

def defaults_and_visibility(indent, config, scope, visibility, description: nil)
  [
    build_default_msg_lines(indent, config, scope, visibility, description: description),
    build_visibility_tag_lines(indent, visibility, config)
  ].flatten
end

.doc_setup(insertion, config:, **opts) ⇒ Hash<Symbol, Object>?

Note:

module_function: defines #doc_setup (visibility: private)

Doc setup

Parameters:

  • insertion (Object)

    the collected method insertion object

  • config (Docscribe::Config)

    Docscribe configuration object

  • opts (Object)

    additional options

Returns:

  • (Hash<Symbol, Object>, nil)


134
135
136
137
138
139
140
141
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 134

def doc_setup(insertion, config:, **opts)
  node = insertion.node
  name = SourceHelpers.node_name(node)
  return nil unless name

  setup = extract_base_setup(insertion, name)
  resolve_doc_setup!(setup, node, name, config, opts)
end

.extract_all_comment_tags(line, info) ⇒ void

Note:

module_function: defines #extract_all_comment_tags (visibility: private)

This method returns an undefined value.

Extract param info

Parameters:

  • line (String)

    single comment line

  • info (Hash<Symbol, Object>)

    parse info hash



531
532
533
534
535
536
537
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 531

def extract_all_comment_tags(line, info)
  extract_param_info(line, info[:param_names], info[:param_types], info[:param_descriptions])
  extract_return_info(line, info)
  extract_visibility_info(line, info)
  extract_raise_info(line, info[:raise_types])
  extract_plugin_info(line, info[:plugin_tags])
end

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

Note:

module_function: defines #extract_args_from_node (visibility: private)

Extract args from node

Parameters:

  • node (Parser::AST::Node)

    AST node whose source text to extract

Returns:

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


1200
1201
1202
1203
1204
1205
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1200

def extract_args_from_node(node)
  case node.type
  when :def then node.children[1]
  when :defs then node.children[2]
  end
end

.extract_base_setup(insertion, name) ⇒ Hash<Symbol, Object>

Note:

module_function: defines #extract_base_setup (visibility: private)

Extract base setup

Parameters:

  • insertion (Object)

    the collected method insertion object

  • name (Symbol)

    the method name string

Returns:

  • (Hash<Symbol, Object>)


206
207
208
209
210
211
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 206

def extract_base_setup(insertion, name)
  n = insertion.node
  { node: n, name: name, indent: SourceHelpers.line_indent(n), scope: insertion.scope,
    visibility: insertion.visibility, container: insertion.container,
    method_symbol: insertion.scope == :instance ? '#' : '.' }
end

.extract_param_description(line) ⇒ String?

Note:

module_function: defines #extract_param_description (visibility: private)

Extract param description

Parameters:

  • line (String)

    a ‘@param` tag line

Returns:

  • (String, nil)


1703
1704
1705
1706
1707
1708
1709
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1703

def extract_param_description(line)
  after = param_rest_after_type(line)
  return nil unless after

  parts = after.split(/\s+/, 2)
  parts[1] if parts.length > 1 && !parts[1].empty?
end

.extract_param_info(line, param_names, param_types, param_descriptions = nil) ⇒ void

Note:

module_function: defines #extract_param_info (visibility: private)

This method returns an undefined value.

Extract param info from tag line

Parameters:

  • line (String)

    a single doc comment line to parse

  • param_names (Hash<String, Boolean>)

    hash tracking existing @param names

  • param_types (Hash<String, String>)

    hash tracking existing @param types

  • param_descriptions (Hash<String, String>, nil) (defaults to: nil)

    param descriptions hash



547
548
549
550
551
552
553
554
555
556
557
558
559
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 547

def extract_param_info(line, param_names, param_types, param_descriptions = nil)
  return unless (pname = extract_param_name_from_param_line(line))

  param_names[pname] = true
  ptype = extract_param_type_from_param_line(line)
  return unless ptype

  param_types[pname] = ptype
  return unless param_descriptions

  desc = extract_param_description(line)
  param_descriptions[pname] = desc if desc
end

.extract_param_name_from_param_line(line) ⇒ String?

Note:

module_function: defines #extract_param_name_from_param_line (visibility: private)

Extract param name from param line

Parameters:

  • line (String)

    a ‘@param` doc line

Returns:

  • (String, nil)

    the parameter name or nil



1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1744

def extract_param_name_from_param_line(line)
  content = line.sub(/^\s*#\s*/, '')
  if (m = content.match(/@param\s+(\S+)\s+\[/))
    return m[1]
  elsif (m = content.match(/@param\s+\[/))
    name_end = m.end(0) #: Integer
    rest = content[(name_end - 1)..] #: String
    type_end = find_matching_close_bracket(rest)
    return name_after_type_bracket(rest, type_end) if type_end
  end

  nil
end

.extract_param_type_from_param_line(line) ⇒ String?

Note:

module_function: defines #extract_param_type_from_param_line (visibility: private)

Extract param type from param line

Parameters:

  • line (String)

    a ‘@param` tag line

Returns:

  • (String, nil)


1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1773

def extract_param_type_from_param_line(line)
  content = line.sub(/^\s*#\s*/, '')
  if (m = content.match(/@param\s+(\S+\s+)?\[/))
    name_end = m.end(0) #: Integer
    rest = content[(name_end - 1)..] #: String
    type_end = find_matching_close_bracket(rest)
    return rest[1...type_end] if type_end
  end
  nil
end

.extract_plugin_info(line, plugin_tags) ⇒ void

Note:

module_function: defines #extract_plugin_info (visibility: private)

This method returns an undefined value.

Extract plugin info

Parameters:

  • line (String)

    a single doc comment line to parse

  • plugin_tags (Hash<String, Boolean>)

    hash tracking existing plugin tag names



682
683
684
685
686
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 682

def extract_plugin_info(line, plugin_tags)
  return unless (m = line.match(/^\s*#\s*@(\w+)\b/))

  plugin_tags[m[1] || ''] = true
end

.extract_raise_info(line, raise_types) ⇒ void

Note:

module_function: defines #extract_raise_info (visibility: private)

This method returns an undefined value.

Extract raise info

Parameters:

  • line (String)

    a single doc comment line to parse

  • raise_types (Hash<String, Boolean>)

    hash tracking existing @raise types



672
673
674
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 672

def extract_raise_info(line, raise_types)
  extract_raise_types_from_line(line).each { |t| raise_types[t || ''] = true }
end

.extract_raise_types_from_line(line) ⇒ Array<String, nil>, Array

Note:

module_function: defines #extract_raise_types_from_line (visibility: private)

Extract raise types from line

Parameters:

  • line (String)

    a ‘@raise` doc line

Returns:

  • (Array<String, nil>)

    if StandardError

  • (Array)

    if StandardError

Raises:

  • (StandardError)


695
696
697
698
699
700
701
702
703
704
705
706
707
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 695

def extract_raise_types_from_line(line)
  return [] unless line.match?(/^\s*#\s*@raise\b/)

  if (m = line.match(/^\s*#\s*@raise\s*\[([^\]]+)\]/))
    parse_raise_bracket_list(m[1]) # steep:ignore ArgumentTypeMismatch
  elsif (m = line.match(/^\s*#\s*@raise\s+([A-Z]\w*(?:::[A-Z]\w*)*)/))
    [m[1]]
  else
    []
  end
rescue StandardError
  []
end

.extract_return_info(line, info) ⇒ void

Note:

module_function: defines #extract_return_info (visibility: private)

This method returns an undefined value.

Extract return info

Parameters:

  • line (String)

    a single doc comment line to parse

  • info (Hash<Symbol, Object>)

    parse info hash to update with return data



567
568
569
570
571
572
573
574
575
576
577
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 567

def extract_return_info(line, info)
  return unless line.match?(/^\s*#\s*@return\b/)

  info[:has_return] = true
  content = line.sub(/^\s*#\s*/, '')
  return unless (m = content.match(/@return\s+/))

  return_type, return_desc = parse_return_rest(m.post_match)
  info[:return_type] = return_type if return_type
  info[:return_description] = return_desc if return_desc
end

.extract_visibility_info(line, info) ⇒ void

Note:

module_function: defines #extract_visibility_info (visibility: private)

This method returns an undefined value.

Extract visibility info

Parameters:

  • line (String)

    a single doc comment line to parse

  • info (Hash<Symbol, Object>)

    parse info hash to update with visibility flags



660
661
662
663
664
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 660

def extract_visibility_info(line, info)
  info[:has_private] ||= line.match?(/^\s*#\s*@private\b/)
  info[:has_protected] ||= line.match?(/^\s*#\s*@protected\b/)
  info[:has_module_function_note] ||= line.match?(/^\s*#\s*@note\s+module_function:/)
end

.find_matching_close_bracket(str) ⇒ Integer?

Note:

module_function: defines #find_matching_close_bracket (visibility: private)

Find matching close bracket

Parameters:

  • str (String)

    string to scan

Returns:

  • (Integer, nil)


1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1789

def find_matching_close_bracket(str)
  depth = 0
  str.each_char.with_index do |c, i|
    case c
    when '[' then depth += 1
    when ']'
      depth -= 1
      return i if depth.zero?
    end
  end
  nil
end

.format_param_tag(indent, name, type, documentation, style:) ⇒ String

Note:

module_function: defines #format_param_tag (visibility: private)

Format param tag

Parameters:

  • indent (String)

    indentation string for the doc line

  • name (String)

    the parameter name

  • type (String)

    the parameter type string

  • documentation (String)

    optional documentation text appended to the tag

  • style (Symbol, String)

    param tag style (:type_name or :name_type)

Returns:

  • (String)


1578
1579
1580
1581
1582
1583
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1578

def format_param_tag(indent, name, type, documentation, style:)
  doc = documentation.to_s.strip
  type = type.to_s
  line = build_param_tag_base(indent, name, type, style)
  doc.empty? ? line : append_param_doc(line, doc, indent)
end

.hash_option_pairs(node) ⇒ Array<Parser::AST::Node>

Note:

module_function: defines #hash_option_pairs (visibility: private)

Hash option pairs

Parameters:

  • node (Parser::AST::Node)

    AST node for the default value, expected to be :hash type

Returns:

  • (Array<Parser::AST::Node>)


1634
1635
1636
1637
1638
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1634

def hash_option_pairs(node)
  return [] unless node&.type == :hash

  node.children.select { |child| child.is_a?(Parser::AST::Node) && child.type == :pair }
end

.init_parse_infoHash<Symbol, Object>

Note:

module_function: defines #init_parse_info (visibility: private)

Init parse info

Returns:

  • (Hash<Symbol, Object>)


369
370
371
372
373
374
375
376
377
378
379
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 369

def init_parse_info
  {
    param_names: {}, param_types: {}, param_descriptions: {},
    raise_types: {}, plugin_tags: {},
    has_return: false, return_type: nil, return_description: nil,
    has_private: false, has_protected: false, has_module_function_note: false,
    description: [],
    last_tag: nil, last_param: nil,
    note_lines: []
  }
end

.join_multiline_tags(lines) ⇒ Array<String>

Note:

module_function: defines #join_multiline_tags (visibility: private)

Join @param/@return/@raise tag lines where the type bracket spans multiple lines.

Parameters:

  • lines (Array<String>)

    doc comment lines

Returns:

  • (Array<String>)


260
261
262
263
264
265
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 260

def join_multiline_tags(lines)
  result = [] #: Array[String]
  i = 0
  i = consume_tag_or_copy(lines, i, result) while i < lines.length
  result
end

.join_tag_continuations(lines, start) ⇒ (String, Integer)

Note:

module_function: defines #join_tag_continuations (visibility: private)

Join continuation lines for a multi-line tag type bracket.

Parameters:

  • lines (Array<String>)

    all doc comment lines

  • start (Integer)

    index of the @param/@return/@raise line

Returns:

  • ((String, Integer))

    joined content and number of lines consumed



291
292
293
294
295
296
297
298
299
300
301
302
303
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 291

def join_tag_continuations(lines, start)
  buffer = +lines[start].sub(/^\s*#\s*/, '').dup
  i = start + 1
  while i < lines.length
    continuation = lines[i].sub(/^\s*#[ \t]/, '')
    break unless continuation.start_with?(' ')

    buffer << continuation.rstrip
    i += 1
    break unless unbalanced_bracket?(buffer)
  end
  [buffer, i - start]
end

.lookup_param_type(external_sig, param_types_override, pname, infer_name, **opts) ⇒ String

Note:

module_function: defines #lookup_param_type (visibility: private)

Lookup param type

Parameters:

  • external_sig (Docscribe::Types::MethodSignature, nil)

    external method signature for type overrides

  • param_types_override (Hash<String, String>, nil)

    map of parameter name to override type

  • pname (String)

    the parameter name string

  • infer_name (String)

    parameter name string or transformed version for inference

  • opts (Object)

    additional options including infer_default, fallback_type, treat_options_keyword_as_hash

Returns:

  • (String)


1544
1545
1546
1547
1548
1549
1550
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1544

def lookup_param_type(external_sig, param_types_override, pname, infer_name, **opts)
  external_sig&.param_types&.[](pname) ||
    override_param_type_for(pname, param_types_override) ||
    Infer.infer_param_type(infer_name, opts[:infer_default],
                           fallback_type: opts[:fallback_type],
                           treat_options_keyword_as_hash: opts[:treat_options_keyword_as_hash])
end

.lookup_param_type_by_infer(param_types_override, pname, infer_name, fallback_type, treat_options_keyword_as_hash) ⇒ String

Note:

module_function: defines #lookup_param_type_by_infer (visibility: private)

Lookup param type by infer

Parameters:

  • param_types_override (Hash<String, String>, nil)

    map of parameter name to override type

  • pname (String)

    the parameter name string

  • infer_name (String)

    parameter name string or transformed version for inference

  • fallback_type (String)

    default type string when inference fails

  • treat_options_keyword_as_hash (Boolean, nil)

    whether to treat options keyword as Hash type

Returns:

  • (String)


1561
1562
1563
1564
1565
1566
1567
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1561

def lookup_param_type_by_infer(param_types_override, pname, infer_name, fallback_type,
                               treat_options_keyword_as_hash)
  override_param_type_for(pname, param_types_override) ||
    Infer.infer_param_type(infer_name, nil,
                           fallback_type: fallback_type,
                           treat_options_keyword_as_hash: treat_options_keyword_as_hash || false)
end

.merge_all_tag_lines(base_ary, **ctx) ⇒ Array<String>

Note:

module_function: defines #merge_all_tag_lines (visibility: private)

Merge all tag lines

Parameters:

  • base_ary (Array<String>)

    initial line array

  • ctx (Object)

    context hash with setup, config, info, insertion, param_types

Returns:

  • (Array<String>)


427
428
429
430
431
432
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 427

def merge_all_tag_lines(base_ary, **ctx)
  line_ary = base_ary.dup
  merge_tag_lines_core(line_ary, ctx)
  line_ary.concat(merge_rescue_return_lines(ctx[:i], ctx[:s][:rescue_specs], ctx[:config], ctx[:info]))
  line_ary
end

.merge_dest_lines(existing_lines, **ctx) ⇒ String?

Note:

module_function: defines #merge_dest_lines (visibility: private)

Merge dest lines

Parameters:

  • existing_lines (Array<String>)

    existing doc comment lines to merge into

  • ctx (Object)

    merge context hash (setup, insertion, config, info, param_types)

Returns:

  • (String, nil)


387
388
389
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 387

def merge_dest_lines(existing_lines, **ctx)
  merge_lines_with_context(existing_lines, **ctx)
end

.merge_lines_with_context(existing_lines, **ctx) ⇒ String

Note:

module_function: defines #merge_lines_with_context (visibility: private)

Merge lines with context

Parameters:

  • existing_lines (Array<String>)

    existing doc comment lines being merged

  • ctx (Object)

    merge context (setup, insertion, config, info, param_types)

Returns:

  • (String)


397
398
399
400
401
402
403
404
405
406
407
408
409
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 397

def merge_lines_with_context(existing_lines, **ctx)
  s = ctx[:setup]
  i = s[:indent]
  config = ctx[:config]
  info = ctx[:info]
  base_ary = build_initial_line_ary(existing_lines, i)
  line_ary = merge_all_tag_lines(base_ary, s: s, i: i, config: config, info: info,
                                           insertion: ctx[:insertion], param_types: ctx[:param_types])
  useful = line_ary.reject { |l| l.strip == '#' }
  return '' if useful.empty?

  line_ary.map { |l| "#{l}\n" }.join
end

.merge_module_function_note_lines(indent, insertion, name, info) ⇒ Array<String>

Note:

module_function: defines #merge_module_function_note_lines (visibility: private)

Merge module function note lines

Parameters:

  • indent (String)

    indentation string for the doc line

  • insertion (Object)

    the collected method insertion object

  • name (String)

    the method name string

  • info (Hash<Symbol, Object>)

    parse info hash to update with visibility flags

Returns:

  • (Array<String>)


828
829
830
831
832
833
834
835
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 828

def merge_module_function_note_lines(indent, insertion, name, info)
  unless insertion.respond_to?(:module_function) && insertion.module_function && !info[:has_module_function_note]
    return []
  end

  included_vis = insertion.included_instance_visibility || :private
  ["#{indent}# @note module_function: defines ##{name} (visibility: #{included_vis})"]
end

.merge_param_lines(node, indent, config:, **opts) ⇒ Array<String>

Note:

module_function: defines #merge_param_lines (visibility: private)

Merge param lines

Parameters:

  • node (Parser::AST::Node)

    AST node whose source text to extract

  • indent (String)

    indentation string for the doc line

  • config (Docscribe::Config)

    Docscribe configuration object

  • opts (Object)

    additional options including external_sig, param_types, info

Returns:

  • (Array<String>)


845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 845

def merge_param_lines(node, indent, config:, **opts)
  return [] unless config.emit_param_tags?

  all_params = build_params_lines(node, indent, external_sig: opts[:external_sig], config: config,
                                                param_types_override: opts[:param_types])
  return [] unless all_params

  info = opts[:info]
  all_params.each_with_object([]) do |pl, result|
    pname = extract_param_name_from_param_line(pl)
    next if pname.nil? || info[:param_names].include?(pname)

    result << pl
  end
end

.merge_raise_tag_lines(node, indent, config, info) ⇒ Array<String>

Note:

module_function: defines #merge_raise_tag_lines (visibility: private)

Merge raise tag lines

Parameters:

  • node (Parser::AST::Node)

    AST node whose source text to extract

  • indent (String)

    indentation string for the doc line

  • config (Docscribe::Config)

    Docscribe configuration object

  • info (Hash<Symbol, Object>)

    parse info hash to update with visibility flags

Returns:

  • (Array<String>)


869
870
871
872
873
874
875
876
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 869

def merge_raise_tag_lines(node, indent, config, info)
  return [] unless config.emit_raise_tags?

  inferred = Docscribe::Infer.infer_raises_from_node(node)
  existing = info[:raise_types] || {}
  inferred.reject { |rt| existing[rt] }
          .map { |rt| "#{indent}# @raise [#{rt}]" }
end

.merge_rescue_return_lines(indent, rescue_specs, config, info) ⇒ Array<String>

Note:

module_function: defines #merge_rescue_return_lines (visibility: private)

Merge rescue return lines

Parameters:

  • indent (String)

    indentation string for the doc line

  • rescue_specs (Array<(Array<String>, String)>)

    rescue type specs

  • config (Docscribe::Config)

    Docscribe configuration object

  • info (Hash<Symbol, Object>)

    parse info hash to update with visibility flags

Returns:

  • (Array<String>)


901
902
903
904
905
906
907
908
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 901

def merge_rescue_return_lines(indent, rescue_specs, config, info)
  return [] unless config.emit_rescue_conditional_returns?
  return [] if info[:has_return]

  rescue_specs.map do |exceptions, rtype|
    "#{indent}# @return [#{rtype}] if #{exceptions.join(', ')}"
  end
end

.merge_return_line(line_ary, indent, setup, config, info) ⇒ void

Note:

module_function: defines #merge_return_line (visibility: private)

This method returns an undefined value.

Merge return line

Parameters:

  • line_ary (Array<String>)

    output line array

  • indent (String)

    indentation string for doc comment lines

  • setup (Hash<Symbol, Object>)

    method setup hash with node, name, types, scope

  • config (Docscribe::Config)

    Docscribe configuration object

  • info (Hash<Symbol, Object>)

    parse info hash to update with visibility flags



481
482
483
484
485
486
487
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 481

def merge_return_line(line_ary, indent, setup, config, info)
  emit_ret = config.emit_return_tag?(setup[:scope], setup[:visibility])
  ret_line = merge_return_tag_line(indent, setup[:normal_type], config: config, scope: setup[:scope],
                                                                visibility: setup[:visibility], info: info)

  line_ary << ret_line if emit_ret && ret_line
end

.merge_return_tag_line(indent, normal_type, config:, **opts) ⇒ String?

Note:

module_function: defines #merge_return_tag_line (visibility: private)

Merge return tag line

Parameters:

  • indent (String)

    indentation string for the doc line

  • normal_type (String)

    resolved return type

  • config (Docscribe::Config)

    Docscribe configuration object

  • opts (Object)

    additional options including scope, visibility, info

Returns:

  • (String, nil)


886
887
888
889
890
891
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 886

def merge_return_tag_line(indent, normal_type, config:, **opts)
  return unless config.emit_return_tag?(opts[:scope], opts[:visibility])
  return if opts[:info][:has_return]

  "#{indent}# @return [#{normal_type}]"
end

.merge_tag_lines_core(line_ary, ctx) ⇒ void

Note:

module_function: defines #merge_tag_lines_core (visibility: private)

This method returns an undefined value.

Merge tag lines core

Parameters:

  • line_ary (Array<String>)

    output line array

  • ctx (Hash<Symbol, Object>)

    merged context hash with info and indent



440
441
442
443
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 440

def merge_tag_lines_core(line_ary, ctx)
  append_merge_tag_lines(line_ary, ctx)
  merge_return_line(line_ary, ctx[:i], ctx[:s], ctx[:config], ctx[:info])
end

.merge_visibility_tag_lines(indent, visibility, config, info) ⇒ Array<String>

Note:

module_function: defines #merge_visibility_tag_lines (visibility: private)

Merge visibility tag lines

Parameters:

  • indent (String)

    indentation string for the doc line

  • visibility (Symbol)

    method visibility symbol

  • config (Docscribe::Config)

    Docscribe configuration object

  • info (Hash<Symbol, Object>)

    parse info hash to update with visibility flags

Returns:

  • (Array<String>)


808
809
810
811
812
813
814
815
816
817
818
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 808

def merge_visibility_tag_lines(indent, visibility, config, info)
  return [] unless config.emit_visibility_tags?

  if visibility == :private && !info[:has_private]
    ["#{indent}# @private"]
  elsif visibility == :protected && !info[:has_protected]
    ["#{indent}# @protected"]
  else
    []
  end
end

.name_after_type_bracket(rest, type_end) ⇒ String?

Note:

module_function: defines #name_after_type_bracket (visibility: private)

Extract name after type bracket

Parameters:

  • rest (String)

    tag content after bracket

  • type_end (Integer)

    closing bracket position

Returns:

  • (String?)


1764
1765
1766
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1764

def name_after_type_bracket(rest, type_end)
  rest[(type_end + 1)..].to_s.strip.split(/\s+/).first
end

.new_plugin_context(insertion, node, source, normal_type) ⇒ Object

Note:

module_function: defines #new_plugin_context (visibility: private)

New plugin context

Parameters:

  • insertion (Object)

    the collected method insertion object

  • node (Parser::AST::Node)

    AST node whose source text to extract

  • source (String)

    method source text

  • normal_type (String)

    resolved return type

Returns:

  • (Object)


1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1983

def new_plugin_context(insertion, node, source, normal_type)
  Docscribe::Plugin::Context.new(
    node: node,
    container: insertion.container,
    scope: insertion.scope,
    visibility: insertion.visibility,
    method_name: SourceHelpers.node_name(node), #: Symbol
    inferred_params: {},
    inferred_return: normal_type,
    source: source
  )
end

.node_default_literal(node) ⇒ String?

Note:

module_function: defines #node_default_literal (visibility: private)

Node default literal

Parameters:

  • node (Parser::AST::Node)

    AST node whose source text to extract

Returns:

  • (String, nil)


1680
1681
1682
1683
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1680

def node_default_literal(node)
  expression = node&.loc&.expression
  expression&.source
end

.optarg_type(pname, default, external_sig, param_types_override, opts) ⇒ String

Note:

module_function: defines #optarg_type (visibility: private)

Optarg type

Parameters:

  • pname (String)

    the parameter name to look up

  • default (Parser::AST::Node)

    default value node

  • external_sig (Docscribe::Types::MethodSignature, nil)

    external method signature for type overrides

  • param_types_override (Hash<String, String>, nil)

    map of parameter name to override type

  • opts (Hash<Symbol, Object>)

    additional options including

Returns:

  • (String)


1412
1413
1414
1415
1416
1417
1418
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1412

def optarg_type(pname, default, external_sig, param_types_override, opts)
  default_src = source_from_node(default)
  lookup_param_type(external_sig, param_types_override, pname, pname,
                    infer_default: default_src,
                    fallback_type: opts[:fallback_type],
                    treat_options_keyword_as_hash: opts[:treat_options_keyword_as_hash])
end

.option_key_name(key_node) ⇒ String

Note:

module_function: defines #option_key_name (visibility: private)

Option key name

Parameters:

  • key_node (Parser::AST::Node)

    AST node for the hash key (:sym or :str type)

Returns:

  • (String)


1665
1666
1667
1668
1669
1670
1671
1672
1673
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1665

def option_key_name(key_node)
  case key_node&.type
  when :sym, :str
    key_node.children.first.to_s
  else
    expression = key_node&.loc&.expression
    expression&.source.to_s.sub(/\A:/, '')
  end
end

.override_param_type_for(pname, override_map) ⇒ String?

Note:

module_function: defines #override_param_type_for (visibility: private)

Override param type for

Parameters:

  • pname (String)

    the parameter name to look up

  • override_map (Hash<Object, Object>, nil)

    hash map of parameter name to override type

Returns:

  • (String, nil)


1691
1692
1693
1694
1695
1696
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1691

def override_param_type_for(pname, override_map)
  return nil unless override_map

  key = pname.to_s
  override_map[key] || override_map[:"#{key}"] || override_map["#{key}:"] || override_map[:"#{key}:"]
end

.param_doc_for_arg(arg, kwargs, config) ⇒ String

Note:

module_function: defines #param_doc_for_arg (visibility: private)

Get param doc for argument

Parameters:

  • arg (Parser::AST::Node)

    individual argument node

  • kwargs (Hash<Symbol, Object>)

    keyword args hash

  • config (Docscribe::Config)

    doc configuration

Returns:

  • (String)


1075
1076
1077
1078
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1075

def param_doc_for_arg(arg, kwargs, config)
  (kwargs[:param_descriptions] || {})[param_name_from_arg(arg)] ||
    (config.include_param_documentation? ? config.param_documentation : '')
end

.param_name_from_arg(arg_node) ⇒ String?

Note:

module_function: defines #param_name_from_arg (visibility: private)

Param name from arg

Parameters:

  • arg_node (Parser::AST::Node)

    AST node for the block argument (&block)

Returns:

  • (String, nil)


1733
1734
1735
1736
1737
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1733

def param_name_from_arg(arg_node)
  return nil if arg_node.type == :forward_arg

  (arg_node.children.first || ARG_DEFAULT_NAMES[arg_node.type] || '').to_s
end

.param_rest_after_type(line) ⇒ String?

Note:

module_function: defines #param_rest_after_type (visibility: private)

Extract everything after the type bracket in a @param line.

Parameters:

  • line (String)

    a @param doc line

Returns:

  • (String?)

    the text after the closing ‘]`, or nil



1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1716

def param_rest_after_type(line)
  content = line.sub(/^\s*#\s*/, '')
  if (m = content.match(/@param\s+(\S+\s+)?\[/))
    brace_end = m.end(0) #: Integer
    rest = content[(brace_end - 1)..] #: String
    type_end = find_matching_close_bracket(rest)
    return rest[(type_end + 1)..]&.strip if type_end
  end
  nil
end

.parse_existing_doc_tags(lines) ⇒ Hash<Symbol, Object>

Note:

module_function: defines #parse_existing_doc_tags (visibility: private)

Parse existing doc tags

Parameters:

  • lines (Array<String>)

    existing doc comment lines

Returns:

  • (Hash<Symbol, Object>)

    parsed tag info



245
246
247
248
249
250
251
252
253
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 245

def parse_existing_doc_tags(lines)
  init = init_parse_info
  tags_started = false
  joined_lines = join_multiline_tags(Array(lines))
  joined_lines.each_with_object(init) do |line, info|
    extract_all_comment_tags(line, info)
    tags_started = parse_existing_tag_line(line, info, tags_started)
  end
end

.parse_existing_tag_line(line, info, tags_started) ⇒ Boolean

Note:

module_function: defines #parse_existing_tag_line (visibility: private)

Parse a single doc comment line for tag info.

Parameters:

  • line (String)

    the doc comment line

  • info (Hash<Symbol, Object>)

    mutable parse info accumulator

  • tags_started (Boolean)

    whether @tags have been seen

Returns:

  • (Boolean)

    updated tags_started



326
327
328
329
330
331
332
333
334
335
336
337
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 326

def parse_existing_tag_line(line, info, tags_started)
  content = line.sub(/^\s*# ?/, '').rstrip
  if content.start_with?('@')
    tags_started = true.tap { track_last_tag(content, info) }
    start_note_tag(line, info) if content.start_with?('@note ')
  elsif tags_started && info[:last_tag]
    append_note_continuation(line, info).tap { append_tag_continuation(content, info) }
  else
    info[:description] << content
  end
  tags_started
end

.parse_raise_bracket_list(str) ⇒ Array<String>

Note:

module_function: defines #parse_raise_bracket_list (visibility: private)

Parse raise bracket list

Parameters:

  • str (String)

    comma-separated exception names string from @raise brackets

Returns:

  • (Array<String>)

    the exception names or nil



714
715
716
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 714

def parse_raise_bracket_list(str)
  str.to_s.split(',').map(&:strip).reject(&:empty?)
end

.parse_return_rest(rest) ⇒ (String, String, nil)?

Note:

module_function: defines #parse_return_rest (visibility: private)

Parse return type from rest string

Parameters:

  • rest (String)

    remaining tag content

Returns:

  • ((String, String, nil), nil)


584
585
586
587
588
589
590
591
592
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 584

def parse_return_rest(rest)
  return unless rest[0] == '['

  type_end = find_matching_close_bracket(rest) or return

  return_type = rest[1...type_end] #: String
  desc = rest[(type_end + 1)..]&.strip
  [return_type, desc&.empty? ? nil : desc]
end

.record_missing_return(lines, reasons, ctx) ⇒ void

Note:

module_function: defines #record_missing_return (visibility: private)

This method returns an undefined value.

Record missing return

Parameters:

  • lines (Array<String>)

    array of output doc lines being accumulated

  • reasons (Array<Hash<Symbol, Object>>)

    array of reason hashes for –explain output

  • ctx (Hash<Symbol, Object>)

    merged context hash with normal_type and indent



1846
1847
1848
1849
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1846

def record_missing_return(lines, reasons, ctx)
  lines << "#{ctx[:indent]}# @return [#{ctx[:normal_type]}]\n"
  reasons << { type: :missing_return, message: 'missing @return' }
end

.record_plugin_tag(tag, lines, reasons, ctx) ⇒ void

Note:

module_function: defines #record_plugin_tag (visibility: private)

This method returns an undefined value.

Record plugin tag

Parameters:

  • tag (Object)

    plugin tag object to render and record

  • lines (Array<String>)

    array of output doc lines being accumulated

  • reasons (Array<Hash<Symbol, Object>>)

    array of reason hashes for –explain output

  • ctx (Hash<Symbol, Object>)

    merged context hash with info and indent



1916
1917
1918
1919
1920
1921
1922
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1916

def record_plugin_tag(tag, lines, reasons, ctx)
  return if ctx[:info][:plugin_tags]&.[](tag.name)

  rendered = render_plugin_tags([tag], ctx[:indent]).first
  lines << "#{rendered}\n"
  reasons << { type: :missing_plugin_tag, message: "missing @#{tag.name}" }
end

.record_updated_return(lines, reasons, ctx) ⇒ void

Note:

module_function: defines #record_updated_return (visibility: private)

This method returns an undefined value.

Record updated return

Parameters:

  • lines (Array<String>)

    array of output doc lines being accumulated

  • reasons (Array<Hash<Symbol, Object>>)

    array of reason hashes for –explain output

  • ctx (Hash<Symbol, Object>)

    merged context hash with normal_type and info



1858
1859
1860
1861
1862
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1858

def record_updated_return(lines, reasons, ctx)
  lines << "#{ctx[:indent]}# @return [#{ctx[:normal_type]}]\n" unless ctx[:strategy] == :safe
  reasons << { type: :updated_return,
               message: "updated @return from #{ctx[:info][:return_type]} to #{ctx[:normal_type]}" }
end

.render_plugin_tags(tags, indent) ⇒ Array<String>

Note:

module_function: defines #render_plugin_tags (visibility: private)

Render plugin tags

Parameters:

  • tags (Array<Object>)

    plugin tag objects

  • indent (String)

    indentation string for the doc line

Returns:

  • (Array<String>)


2015
2016
2017
2018
2019
2020
2021
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 2015

def render_plugin_tags(tags, indent)
  tags.map do |tag|
    type_part = tag.types&.any? ? " [#{tag.types.join(', ')}]" : ''
    text_part = tag.text ? " #{tag.text}" : ''
    "#{indent}# @#{tag.name}#{type_part}#{text_part}"
  end
end

.resolve_doc_setup!(setup, node, name, config, opts) ⇒ Hash<Symbol, Object>

Note:

module_function: defines #resolve_doc_setup! (visibility: private)

Resolve doc setup

Parameters:

  • setup (Hash<Symbol, Object>)

    method setup hash with name, normal_type, scope, visibility

  • node (Parser::AST::Node)

    AST node whose source text to extract

  • name (Symbol)

    the method name string

  • config (Docscribe::Config)

    Docscribe configuration object

  • opts (Hash<Symbol, Object>)

    additional options including

Returns:

  • (Hash<Symbol, Object>)


188
189
190
191
192
193
194
195
196
197
198
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 188

def resolve_doc_setup!(setup, node, name, config, opts)
  external_sig = resolve_external_sig(setup[:container], setup[:scope], name, opts[:signature_provider])
  returns_spec = compute_returns_spec(node, config, opts[:param_types], opts[:core_rbs_provider])
  normal_type = opts[:return_type_override] || external_sig&.return_type || returns_spec[:normal]

  setup.merge(
    external_sig: external_sig,
    normal_type: normal_type,
    rescue_specs: returns_spec[:rescues] || []
  )
end

.resolve_external_sig(container, scope, name, signature_provider) ⇒ Docscribe::Types::MethodSignature?

Note:

module_function: defines #resolve_external_sig (visibility: private)

Resolve external sig

Parameters:

  • container (String)

    method container name

  • scope (Symbol)

    method scope symbol

  • name (Symbol)

    the method name string

  • signature_provider (Docscribe::Types::ProviderChain, nil)

    external sig provider

Returns:



221
222
223
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 221

def resolve_external_sig(container, scope, name, signature_provider)
  signature_provider&.signature_for(container: container, scope: scope, name: name)
end

.resolve_infer_name(pname, infer_name) ⇒ String

Note:

module_function: defines #resolve_infer_name (visibility: private)

Resolve infer name

Parameters:

  • pname (String)

    the parameter name to look up

  • infer_name (Proc, nil)

    parameter name string or transformed version for inference

Returns:

  • (String)


1436
1437
1438
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1436

def resolve_infer_name(pname, infer_name)
  infer_name ? infer_name.call(pname) : pname
end

.return_type_changed?(ctx) ⇒ Boolean

Note:

module_function: defines #return_type_changed? (visibility: private)

Return type changed

Parameters:

  • ctx (Hash<Symbol, Object>)

    merged context hash with external_sig, info, and normal_type

Returns:

  • (Boolean)


1869
1870
1871
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1869

def return_type_changed?(ctx)
  ctx[:external_sig] && ctx[:info][:return_type] && ctx[:info][:return_type] != ctx[:normal_type]
end

.safe_node_source(node) ⇒ String

Note:

module_function: defines #safe_node_source (visibility: private)

Safe node source

Parameters:

  • node (Parser::AST::Node)

    AST node whose source text to extract

Returns:

  • (String)

    if StandardError

  • (String)

    if StandardError

Raises:

  • (StandardError)


2003
2004
2005
2006
2007
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 2003

def safe_node_source(node)
  node.loc.expression.source
rescue StandardError
  ''
end

.source_from_node(node) ⇒ String?

Note:

module_function: defines #source_from_node (visibility: private)

Source from node

Parameters:

  • node (Parser::AST::Node)

    AST node whose source text to extract

Returns:

  • (String, nil)


1425
1426
1427
1428
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1425

def source_from_node(node)
  loc = node&.loc
  loc&.expression&.source
end

.start_note_tag(line, info) ⇒ void

Note:

module_function: defines #start_note_tag (visibility: private)

This method returns an undefined value.

Start a note tag

Parameters:

  • line (String)

    doc comment line

  • info (Hash<Symbol, Object>)

    parse info hash



345
346
347
348
349
350
351
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 345

def start_note_tag(line, info)
  return if line.match?(/^\s*#\s*@note\s+module_function:/)

  empty = [] #: Array[String]
  info[:note_lines] << empty
  info[:note_lines].last << line.chomp
end

.track_last_tag(content, info) ⇒ void

Note:

module_function: defines #track_last_tag (visibility: private)

This method returns an undefined value.

Extract all comment tags from line

Parameters:

  • content (String)
  • info (Hash<Symbol, Object>)

    parse info hash



600
601
602
603
604
605
606
607
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 600

def track_last_tag(content, info)
  tag = content.match(/@(\w+)/)&.[](1)&.to_sym
  info[:last_tag] = tag
  return unless tag == :param

  pname = extract_param_name_from_param_line(content)
  info[:last_param] = pname if pname
end

.unbalanced_bracket?(str) ⇒ Boolean

Note:

module_function: defines #unbalanced_bracket? (visibility: private)

Check if bracket depth is positive (an opening ‘[` is unclosed).

Parameters:

  • str (String)

    string to check

Returns:

  • (Boolean)


310
311
312
313
314
315
316
317
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 310

def unbalanced_bracket?(str)
  depth = 0
  str.each_char do |c|
    depth += 1 if c == '['
    depth -= 1 if c == ']'
  end
  depth.positive?
end