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



937
938
939
940
941
942
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 937

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



951
952
953
954
955
956
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 951

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



1129
1130
1131
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1129

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



457
458
459
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 457

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)


365
366
367
368
369
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 365

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



1629
1630
1631
1632
1633
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1629

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)


1613
1614
1615
1616
1617
1618
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1613

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



621
622
623
624
625
626
627
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 621

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



649
650
651
652
653
654
655
656
657
658
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 649

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



635
636
637
638
639
640
641
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 635

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


1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1109

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


1140
1141
1142
1143
1144
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1140

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


466
467
468
469
470
471
472
473
474
475
476
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 466

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)


1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1061

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)


1381
1382
1383
1384
1385
1386
1387
1388
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1381

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)


1532
1533
1534
1535
1536
1537
1538
1539
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1532

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)


1951
1952
1953
1954
1955
1956
1957
1958
1959
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1951

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


1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1266

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


1093
1094
1095
1096
1097
1098
1099
1100
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1093

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


1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1245

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


423
424
425
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 423

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)


1455
1456
1457
1458
1459
1460
1461
1462
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1455

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)


1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1473

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)


1515
1516
1517
1518
1519
1520
1521
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1515

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


1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1302

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


1399
1400
1401
1402
1403
1404
1405
1406
1407
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1399

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)


1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1654

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


1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1222

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)


1599
1600
1601
1602
1603
1604
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1599

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)


731
732
733
734
735
736
737
738
739
740
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 731

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)


1045
1046
1047
1048
1049
1050
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1045

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)


1975
1976
1977
1978
1979
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1975

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


1366
1367
1368
1369
1370
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1366

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


1322
1323
1324
1325
1326
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1322

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


1350
1351
1352
1353
1354
1355
1356
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1350

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)


1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1494

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


1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1190

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)


1337
1338
1339
1340
1341
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1337

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


1285
1286
1287
1288
1289
1290
1291
1292
1293
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1285

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


504
505
506
507
508
509
510
511
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 504

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



750
751
752
753
754
755
756
757
758
759
760
761
762
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 750

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


518
519
520
521
522
523
524
525
526
527
528
529
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 518

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



965
966
967
968
969
970
971
972
973
974
975
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 965

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



984
985
986
987
988
989
990
991
992
993
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 984

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



1906
1907
1908
1909
1910
1911
1912
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1906

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



1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1815

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



1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1886

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



1835
1836
1837
1838
1839
1840
1841
1842
1843
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1835

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



923
924
925
926
927
928
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 923

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



793
794
795
796
797
798
799
800
801
802
803
804
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 793

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



1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1003

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



773
774
775
776
777
778
779
780
781
782
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 773

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



1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1024

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, signature_provider: nil, container: nil) ⇒ 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

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

Returns:

  • (Hash<Symbol, Object>)


237
238
239
240
241
242
243
244
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 237

def compute_returns_spec(node, config, param_types, core_rbs_provider, # rubocop:disable Metrics/ParameterLists
                         signature_provider: nil, container: nil)
  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,
          signature_provider: signature_provider, container: container
  )
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)


280
281
282
283
284
285
286
287
288
289
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 280

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


1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1153

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)


1965
1966
1967
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1965

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



1938
1939
1940
1941
1942
1943
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1938

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


1175
1176
1177
1178
1179
1180
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1175

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



537
538
539
540
541
542
543
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 537

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)


1206
1207
1208
1209
1210
1211
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1206

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


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

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)


1709
1710
1711
1712
1713
1714
1715
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1709

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



553
554
555
556
557
558
559
560
561
562
563
564
565
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 553

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



1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1750

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)


1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1779

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



688
689
690
691
692
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 688

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



678
679
680
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 678

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>)
  • (Array)

    if StandardError

Raises:

  • (StandardError)


701
702
703
704
705
706
707
708
709
710
711
712
713
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 701

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



573
574
575
576
577
578
579
580
581
582
583
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 573

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



666
667
668
669
670
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 666

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)


1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1795

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)


1584
1585
1586
1587
1588
1589
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1584

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


1640
1641
1642
1643
1644
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1640

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


375
376
377
378
379
380
381
382
383
384
385
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 375

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


266
267
268
269
270
271
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 266

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



297
298
299
300
301
302
303
304
305
306
307
308
309
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 297

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)


1550
1551
1552
1553
1554
1555
1556
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1550

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)


1567
1568
1569
1570
1571
1572
1573
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1567

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


433
434
435
436
437
438
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 433

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)


393
394
395
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 393

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)


403
404
405
406
407
408
409
410
411
412
413
414
415
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 403

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


834
835
836
837
838
839
840
841
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 834

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


851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 851

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


875
876
877
878
879
880
881
882
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 875

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


907
908
909
910
911
912
913
914
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 907

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



487
488
489
490
491
492
493
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 487

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)


892
893
894
895
896
897
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 892

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



446
447
448
449
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 446

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


814
815
816
817
818
819
820
821
822
823
824
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 814

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


1770
1771
1772
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1770

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)


1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1989

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)


1686
1687
1688
1689
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1686

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)


1418
1419
1420
1421
1422
1423
1424
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1418

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)


1671
1672
1673
1674
1675
1676
1677
1678
1679
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1671

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)


1697
1698
1699
1700
1701
1702
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1697

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)


1081
1082
1083
1084
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1081

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)


1739
1740
1741
1742
1743
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1739

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



1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1722

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



251
252
253
254
255
256
257
258
259
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 251

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



332
333
334
335
336
337
338
339
340
341
342
343
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 332

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



720
721
722
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 720

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)


590
591
592
593
594
595
596
597
598
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 590

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



1852
1853
1854
1855
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1852

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



1922
1923
1924
1925
1926
1927
1928
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1922

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



1864
1865
1866
1867
1868
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1864

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


2021
2022
2023
2024
2025
2026
2027
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 2021

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
199
200
# 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],
                                      signature_provider: opts[:signature_provider],
                                      container: setup[:container])
  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:



223
224
225
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 223

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)


1442
1443
1444
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1442

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)


1875
1876
1877
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1875

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)
  • (String)

    if StandardError

Raises:

  • (StandardError)


2009
2010
2011
2012
2013
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 2009

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)


1431
1432
1433
1434
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1431

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



351
352
353
354
355
356
357
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 351

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



606
607
608
609
610
611
612
613
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 606

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)


316
317
318
319
320
321
322
323
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 316

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