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



991
992
993
994
995
996
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 991

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



1005
1006
1007
1008
1009
1010
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1005

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 (Docscribe::InlineRewriter::DocBuilder::setup)

    method setup hash with name, types, scope

  • ctx (Hash<Symbol, Object>)

    merged context hash with info and indent



1310
1311
1312
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1310

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



477
478
479
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 477

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 (Docscribe::InlineRewriter::DocBuilder::parseInfo)

    parse info hash

Returns:

  • (Object)


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

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



1808
1809
1810
1811
1812
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1808

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)


1792
1793
1794
1795
1796
1797
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1792

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_param_update(param_line, pname, new_type, lines, reasons, ctx) ⇒ void

Note:

module_function: defines #append_param_update (visibility: private)

This method returns an undefined value.

Parameters:

  • param_line (String)
  • pname (String)
  • new_type (String, nil)
  • lines (Array<String>)
  • reasons (Array<Hash<Symbol, Object>>)
  • ctx (Hash<Symbol, Object>)


1207
1208
1209
1210
1211
1212
1213
1214
1215
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1207

def append_param_update(param_line, pname, new_type, lines, reasons, ctx) # rubocop:disable Metrics/ParameterLists
  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}",
    source: ctx[:external_sig] ? 'rbs' : 'infer',
    extra: { param: pname }
  }
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 (Docscribe::InlineRewriter::DocBuilder::parseInfo)

    parse info hash



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

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 (Docscribe::InlineRewriter::DocBuilder::parseInfo)

    parse info hash



685
686
687
688
689
690
691
692
693
694
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 685

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 (Docscribe::InlineRewriter::DocBuilder::parseInfo)

    parse info hash



671
672
673
674
675
676
677
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 671

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 (Docscribe::InlineRewriter::DocBuilder::setup)

    setup

  • ctx (Hash<Symbol, Object>)

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

Returns:

  • (Array<String>)


1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1290

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

.bare_raise_type(line) ⇒ String?

Note:

module_function: defines #bare_raise_type (visibility: private)

Bare raise type from line

Parameters:

  • line (String)

    a @raise doc line

Returns:

  • (String, nil)


763
764
765
766
767
768
769
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 763

def bare_raise_type(line)
  m = line.match(/^\s*#\s*@raise\s+([A-Z]\w*(?:::[A-Z]\w*)*)/)
  return nil unless m

  captured = m[1]
  captured ? [captured] : []
end

.bracketed_raise_types(line) ⇒ Array<String>?

Note:

module_function: defines #bracketed_raise_types (visibility: private)

Bracketed raise types from line

Parameters:

  • line (String)

    a @raise doc line

Returns:

  • (Array<String>, nil)


750
751
752
753
754
755
756
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 750

def bracketed_raise_types(line)
  m = line.match(/^\s*#\s*@raise\s*\[([^\]]+)\]/)
  return nil unless m

  captured = m[1]
  captured ? parse_raise_bracket_list(captured) : []
end

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

Note:

module_function: defines #build (visibility: private)

Build

Parameters:

Returns:

  • (String, nil)
  • (nil)

    if StandardError

Raises:

  • (StandardError)


75
76
77
78
79
80
81
82
83
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 75

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 (Docscribe::InlineRewriter::DocBuilder::setup)

    method setup hash with name, types, scope

  • ctx (Hash<Symbol, Object>)

    merged context hash with info and indent

Returns:

  • (Array<String>)


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

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


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

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 (Hash<Symbol, Object>)

    additional keyword args including insertion, params_lines, raise_types, override_tags

Returns:

  • (Array<String>, nil)


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

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 (Hash<Symbol, Object>)

    additional options for param formatting

Returns:

  • (String)


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

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 (Hash<Symbol, Object>)

    additional options for param formatting

Returns:

  • (String)


1711
1712
1713
1714
1715
1716
1717
1718
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1711

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:

Returns:

  • (String)


2347
2348
2349
2350
2351
2352
2353
2354
2355
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 2347

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


1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1445

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 (Docscribe::InlineRewriter::DocBuilder::setup)

    method setup hash with indent, name, types, scope

  • config (Docscribe::Config)

    Docscribe configuration object

  • kwargs (Hash<Symbol, Object>)

    additional keyword args including insertion, params_lines, raise_types, override_tags

Returns:

  • (Array<String>)


1274
1275
1276
1277
1278
1279
1280
1281
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1274

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 (Hash<Symbol, Object>)

    additional options including container, method_symbol, name, normal_type

Returns:

  • (Array<String>)


1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1424

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


443
444
445
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 443

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 (Hash<Symbol, Object>)

    additional options for param formatting

Returns:

  • (String)


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

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 (Hash<Symbol, Object>)

    additional options for param formatting

Returns:

  • (String)


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

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 (Hash<Symbol, Object>)

    additional options for param formatting

Returns:

  • (String)


1694
1695
1696
1697
1698
1699
1700
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1694

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 (Docscribe::InlineRewriter::Collector::Insertion)

    the collected method insertion object

  • existing_lines (Array<String>)

    existing doc comment lines being merged

  • config (Docscribe::Config)

    Docscribe configuration object

  • options (Hash<Symbol, Object>)

    additional keyword options forwarded to downstream methods

Returns:

  • (String, nil)
  • (nil)

    if StandardError

Raises:

  • (StandardError)


95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 95

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) ⇒ Docscribe::InlineRewriter::DocBuilder::missingMergeResult, Hash

Note:

module_function: defines #build_missing_merge_result (visibility: private)

Build missing merge result

Parameters:

  • insertion (Docscribe::InlineRewriter::Collector::Insertion)

    the collected method insertion object

  • existing_lines (Array<String>)

    existing doc comment lines being merged

  • config (Docscribe::Config)

    Docscribe configuration object

  • options (Hash<Symbol, Object>)

    additional keyword options forwarded to downstream methods

Returns:

  • (Docscribe::InlineRewriter::DocBuilder::missingMergeResult)
  • (Hash)

    if StandardError

Raises:

  • (StandardError)


118
119
120
121
122
123
124
125
126
127
128
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 118

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:

Returns:

  • (Array<String>)


1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1481

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 (Hash<Symbol, Object>)

    additional options for param formatting

Returns:

  • (Array<String>)


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

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)


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

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 (Docscribe::InlineRewriter::DocBuilder::setup)

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


170
171
172
173
174
175
176
177
178
179
180
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 170

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 (Hash<Symbol, Object>)

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

Returns:

  • (Array<String>)


1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1403

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"
  return send(method_name, arg_node, indent, external_sig, param_types_override, **opts) if respond_to?(method_name, true)

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


1778
1779
1780
1781
1782
1783
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1778

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)


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

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)


1226
1227
1228
1229
1230
1231
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1226

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:) ⇒ Docscribe::Plugin::Context

Note:

module_function: defines #build_plugin_context (visibility: private)

Build plugin context

Parameters:

Returns:



2371
2372
2373
2374
2375
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 2371

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:

Returns:

  • (Array<String>)


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

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


1501
1502
1503
1504
1505
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1501

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


1529
1530
1531
1532
1533
1534
1535
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1529

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 (Hash<Symbol, Object>)

    additional options for param formatting

Returns:

  • (String)


1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1673

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 (Docscribe::InlineRewriter::DocBuilder::setup)

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


1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1371

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)


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

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 (Docscribe::InlineRewriter::Collector::Insertion)

    the collected method insertion object

  • config (Docscribe::Config)

    Docscribe configuration object

  • setup (Docscribe::InlineRewriter::DocBuilder::setup)

    method setup hash with name, normal_type, scope, visibility

  • opts (Hash<Symbol, Object>)

    additional options including infer_default, fallback_type, treat_options_keyword_as_hash

Returns:

  • (String)


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

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


1464
1465
1466
1467
1468
1469
1470
1471
1472
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1464

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) ⇒ Docscribe::InlineRewriter::DocBuilder::missingMergeResult

Note:

module_function: defines #collect_all_missing (visibility: private)

Collect all missing

Parameters:

  • setup (Docscribe::InlineRewriter::DocBuilder::setup)

    resolved setup hash with node, name, indent, types

  • info (Docscribe::InlineRewriter::DocBuilder::parseInfo)

    parsed existing doc tag information

  • insertion (Docscribe::InlineRewriter::Collector::Insertion)

    the collected method insertion object

  • config (Docscribe::Config)

    Docscribe configuration object

  • options (Hash<Symbol, Object>)

    additional options hash forwarded to missing collector

Returns:

  • (Docscribe::InlineRewriter::DocBuilder::missingMergeResult)


524
525
526
527
528
529
530
531
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 524

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



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

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) ⇒ Docscribe::InlineRewriter::DocBuilder::missingMergeResult

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:

  • (Docscribe::InlineRewriter::DocBuilder::missingMergeResult)


538
539
540
541
542
543
544
545
546
547
548
549
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 538

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 (Hash<Symbol, Object>)

    merged context hash with info and indent



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

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 (Hash<Symbol, Object>)

    merged context hash with info and indent



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

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 (Hash<Symbol, Object>)

    merged context hash with info and indent



2302
2303
2304
2305
2306
2307
2308
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 2302

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 (Hash<Symbol, Object>)

    merged context hash with info and indent



1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1994

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 (Hash<Symbol, Object>)

    merged context hash with info and indent



2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 2282

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 (Hash<Symbol, Object>)

    merged context hash with info and indent



2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 2014

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 invalid_yard_return?(ctx)
    record_invalid_return(lines, reasons, ctx)
  elsif return_type_changed?(ctx)
    record_updated_return(lines, reasons, ctx)
  elsif should_validate_return?(ctx) && mismatched_return?(ctx) # rubocop:disable Lint/DuplicateBranch
    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 (Hash<Symbol, Object>)

    merged context hash with info and indent



977
978
979
980
981
982
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 977

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



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

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



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

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

  if missing_param?(pname, ctx)
    handle_missing_param(pname, param_line, lines, reasons)
  elsif existing_param_type?(pname, ctx)
    handle_existing_param(pname, param_line, 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



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

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



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

def collect_updated_param(param_line, pname, lines, reasons, ctx)
  new_type = extract_param_type_from_param_line(param_line)
  return unless param_type_changed?(pname, new_type, ctx)
  return if fallback_skipped?(new_type, ctx)

  append_param_update(param_line, pname, new_type, lines, reasons, ctx)
end

.compute_returns_spec(node, config, param_types, core_rbs_provider, signature_provider: nil, container: nil) ⇒ Docscribe::InlineRewriter::DocBuilder::returnsSpec

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 (Docscribe::Types::RBS::Provider, nil)

    RBS type provider

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

Returns:

  • (Docscribe::InlineRewriter::DocBuilder::returnsSpec)


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

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

.conditional_return_desc?(desc) ⇒ Boolean

Note:

module_function: defines #conditional_return_desc? (visibility: private)

Whether a return description marks a rescue-conditional tag.

Parameters:

  • desc (String, nil)

    description after the type brackets

Returns:

  • (Boolean)

    true for "if Error" suffixes



617
618
619
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 617

def conditional_return_desc?(desc)
  desc.to_s.start_with?('if ')
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)


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

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

Note:

module_function: defines #core_body_tags (visibility: private)

Core body tags

Parameters:

  • indent (String)

    indentation string for doc comment lines

  • setup (Docscribe::InlineRewriter::DocBuilder::setup)

    method setup hash with name, types, scope

  • ctx (Hash<Symbol, Object>)

    merged context hash with info and indent

Returns:

  • (Array<String>)


1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1334

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)


2361
2362
2363
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 2361

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:



2334
2335
2336
2337
2338
2339
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 2334

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


1356
1357
1358
1359
1360
1361
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1356

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) ⇒ Docscribe::InlineRewriter::DocBuilder::setup?

Note:

module_function: defines #doc_setup (visibility: private)

Doc setup

Parameters:

Returns:

  • (Docscribe::InlineRewriter::DocBuilder::setup, nil)


137
138
139
140
141
142
143
144
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 137

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

.existing_param_type?(pname, ctx) ⇒ Boolean

Note:

module_function: defines #existing_param_type? (visibility: private)

Parameters:

  • pname (String)
  • ctx (Hash<Symbol, Object>)

Returns:

  • (Boolean)


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

def existing_param_type?(pname, ctx)
  !!ctx[:info][:param_types][pname]
end

.expected_suppressed?(expected, fallback) ⇒ Boolean

Note:

module_function: defines #expected_suppressed? (visibility: private)

Whether expected type is suppressed as fallback.

Parameters:

  • expected (String?)
  • fallback (String)

Returns:

  • (Boolean)


2117
2118
2119
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 2117

def expected_suppressed?(expected, fallback)
  expected == fallback || fallback_union?(expected, fallback)
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 (Docscribe::InlineRewriter::DocBuilder::parseInfo)

    parse info hash



557
558
559
560
561
562
563
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 557

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)


1387
1388
1389
1390
1391
1392
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1387

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) ⇒ Docscribe::InlineRewriter::DocBuilder::setup

Note:

module_function: defines #extract_base_setup (visibility: private)

Extract base setup

Parameters:

Returns:

  • (Docscribe::InlineRewriter::DocBuilder::setup)


211
212
213
214
215
216
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 211

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_method_name(ctx) ⇒ Symbol?

Note:

module_function: defines #extract_method_name (visibility: private)

Extract method name for void compatibility dynamic check.

Parameters:

  • ctx (Hash<Symbol, Object>)

    context hash with insertion or node

Returns:

  • (Symbol, nil)
  • (nil)

    if StandardError

Raises:

  • (StandardError)


2092
2093
2094
2095
2096
2097
2098
2099
2100
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 2092

def extract_method_name(ctx)
  insertion = ctx[:insertion]
  node = insertion&.node || ctx[:node]
  return nil unless node

  SourceHelpers.node_name(node)
rescue StandardError
  nil
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)


1888
1889
1890
1891
1892
1893
1894
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1888

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



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

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



1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1929

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)


1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1958

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



724
725
726
727
728
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 724

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



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

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)


737
738
739
740
741
742
743
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 737

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

  bracketed_raise_types(line) || bare_raise_type(line) || []
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 (Docscribe::InlineRewriter::DocBuilder::parseInfo)

    parse info hash to update with return data



593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 593

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)
  return unless return_type
  # Rescue-conditional `@return [X] if Error` tags describe rescue
  # branches (see rescue_conditional_returns) and must not overwrite
  # the main return type — otherwise check demands the conditional
  # type while update_types regenerates it, ping-ponging forever.
  return if conditional_return_desc?(return_desc)

  info[:return_type] = return_type
  info[:return_description] = return_desc if return_desc
end

.extract_sig_param_info(node) ⇒ (Integer?, Array<String>)

Note:

module_function: defines #extract_sig_param_info (visibility: private)

Parameters:

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

Returns:

  • ((Integer?, Array<String>))


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

def extract_sig_param_info(node)
  empty = [] #: Array[String]
  return [nil, empty] unless node

  args = extract_args_from_node(node)
  empty = [] #: Array[String]
  return [nil, empty] unless args

  [args.children.length, args.children.map { |a| a.children.first.to_s if a.respond_to?(:children) }.compact]
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 (Docscribe::InlineRewriter::DocBuilder::parseInfo)

    parse info hash to update with visibility flags



702
703
704
705
706
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 702

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

.fallback_skipped?(new_type, ctx) ⇒ Boolean

Note:

module_function: defines #fallback_skipped? (visibility: private)

Parameters:

  • new_type (String, nil)
  • ctx (Hash<Symbol, Object>)

Returns:

  • (Boolean)


1195
1196
1197
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1195

def fallback_skipped?(new_type, ctx)
  ctx[:config].respond_to?(:validate_types?) && ctx[:config].validate_types? && (new_type == ctx[:config].fallback_type)
end

.fallback_union?(type_str, fallback) ⇒ Boolean

Note:

module_function: defines #fallback_union? (visibility: private)

Whether a type string is a union of only fallback types (with optional ?).

Parameters:

  • type_str (String, nil)
  • fallback (String)

Returns:

  • (Boolean)


2221
2222
2223
2224
2225
2226
2227
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 2221

def fallback_union?(type_str, fallback)
  return false if type_str.nil? || type_str.strip.empty?

  fallback_norm = normalize_type(fallback)
  parts = type_str.to_s.split(',').map { |p| normalize_type(p.strip.delete_suffix('?').strip) }
  parts.all? { |p| p == fallback_norm || p.empty? }
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)


1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1974

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)


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

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

.generic_compatible?(yard, expected, method_name: nil) ⇒ Boolean

Note:

module_function: defines #generic_compatible? (visibility: private)

Delegates to GenericCompatibility service (dynamic, map-dispatched, no hardcodes).

Parameters:

  • yard (String)
  • expected (String)
  • method_name (String, Symbol, nil) (defaults to: nil)

    method name for void compatibility threading

Returns:

  • (Boolean)


2172
2173
2174
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 2172

def generic_compatible?(yard, expected, method_name: nil)
  Docscribe::Validator::GenericCompatibility.compatible?(yard, expected, fallback_type: 'Object', method_name: method_name)
end

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

Note:

module_function: defines #handle_existing_param (visibility: private)

This method returns an undefined value.

Parameters:

  • pname (String)
  • param_line (String)
  • lines (Array<String>)
  • reasons (Array<Hash<Symbol, Object>>)
  • ctx (Hash<Symbol, Object>)


1102
1103
1104
1105
1106
1107
1108
1109
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1102

def handle_existing_param(pname, param_line, lines, reasons, ctx)
  yard_type = ctx[:info][:param_types][pname]
  if invalid_yard_type?(yard_type)
    handle_invalid_param(pname, param_line, yard_type, lines, reasons)
  elsif param_needs_update?(ctx)
    collect_updated_param(param_line, pname, lines, reasons, ctx)
  end
end

.handle_invalid_param(pname, param_line, yard_type, lines, reasons) ⇒ void

Note:

module_function: defines #handle_invalid_param (visibility: private)

This method returns an undefined value.

Parameters:

  • pname (String)
  • param_line (String)
  • yard_type (String)
  • lines (Array<String>)
  • reasons (Array<Hash<Symbol, Object>>)


1118
1119
1120
1121
1122
1123
1124
1125
1126
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1118

def handle_invalid_param(pname, param_line, yard_type, lines, reasons)
  lines << "#{param_line}\n"
  reasons << {
    type: :invalid_type,
    message: "invalid YARD type [#{yard_type}] for @param #{pname}",
    source: 'syntax',
    extra: { param: pname }
  }
end

.handle_missing_param(pname, param_line, lines, reasons) ⇒ void

Note:

module_function: defines #handle_missing_param (visibility: private)

This method returns an undefined value.

Parameters:

  • pname (String)
  • param_line (String)
  • lines (Array<String>)
  • reasons (Array<Hash<Symbol, Object>>)


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

def handle_missing_param(pname, param_line, lines, reasons)
  lines << "#{param_line}\n"
  reasons << { type: :missing_param, message: "missing @param #{pname}", extra: { param: pname } }
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>)


1819
1820
1821
1822
1823
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1819

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_infoDocscribe::InlineRewriter::DocBuilder::parseInfo

Note:

module_function: defines #init_parse_info (visibility: private)

Init parse info

Returns:

  • (Docscribe::InlineRewriter::DocBuilder::parseInfo)


395
396
397
398
399
400
401
402
403
404
405
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 395

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

.invalid_yard_return?(ctx) ⇒ Boolean

Note:

module_function: defines #invalid_yard_return? (visibility: private)

Whether YARD return type has invalid syntax.

Parameters:

  • ctx (Hash<Symbol, Object>)

Returns:

  • (Boolean)


2033
2034
2035
2036
2037
2038
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 2033

def invalid_yard_return?(ctx)
  yard = ctx[:info][:return_type]
  return false unless yard

  invalid_yard_type?(yard)
end

.invalid_yard_type?(type_str) ⇒ Boolean

Note:

module_function: defines #invalid_yard_type? (visibility: private)

Whether a YARD type string has invalid syntax.

Called from both param (above) and return (below) validation, so no waterfall placement satisfies the ordering cop — exempt.

Parameters:

  • type_str (String?)

Returns:

  • (Boolean)


1143
1144
1145
1146
1147
1148
1149
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1143

def invalid_yard_type?(type_str) # rubocop:disable SortedMethodsByCall/Waterfall
  return false if type_str.nil? || type_str.strip.empty?
  return true if type_str.match?(/\d/)
  return true if type_str.match?(/[^\x00-\x7F]/)

  !Types::Yard::Validator.valid?(type_str)
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>)


286
287
288
289
290
291
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 286

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



317
318
319
320
321
322
323
324
325
326
327
328
329
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 317

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 (Hash<Symbol, Object>)

    additional options including infer_default, fallback_type, treat_options_keyword_as_hash

Returns:

  • (String)


1729
1730
1731
1732
1733
1734
1735
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1729

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)


1746
1747
1748
1749
1750
1751
1752
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1746

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 (Hash<Symbol, Object>)

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

Returns:

  • (Array<String>)


453
454
455
456
457
458
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 453

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 (Hash<Symbol, Object>)

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

Returns:

  • (String, nil)


413
414
415
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 413

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 (Hash<Symbol, Object>)

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

Returns:

  • (String)


423
424
425
426
427
428
429
430
431
432
433
434
435
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 423

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 (Docscribe::InlineRewriter::Collector::Insertion)

    the collected method insertion object

  • name (String)

    the method name string

  • info (Docscribe::InlineRewriter::DocBuilder::parseInfo)

    parse info hash to update with visibility flags

Returns:

  • (Array<String>)


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

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

  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 (Hash<Symbol, Object>)

    additional options including external_sig, param_types, info

Returns:

  • (Array<String>)


905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 905

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 (Docscribe::InlineRewriter::DocBuilder::parseInfo)

    parse info hash to update with visibility flags

Returns:

  • (Array<String>)


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

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 (Docscribe::InlineRewriter::DocBuilder::parseInfo)

    parse info hash to update with visibility flags

Returns:

  • (Array<String>)


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

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 (Docscribe::InlineRewriter::DocBuilder::setup)

    method setup hash with node, name, types, scope

  • config (Docscribe::Config)

    Docscribe configuration object

  • info (Docscribe::InlineRewriter::DocBuilder::parseInfo)

    parse info hash to update with visibility flags



507
508
509
510
511
512
513
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 507

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 (Hash<Symbol, Object>)

    additional options including scope, visibility, info

Returns:

  • (String, nil)


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

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



466
467
468
469
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 466

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 (Docscribe::InlineRewriter::DocBuilder::parseInfo)

    parse info hash to update with visibility flags

Returns:

  • (Array<String>)


870
871
872
873
874
875
876
877
878
879
880
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 870

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

.mismatched_return?(ctx) ⇒ Boolean

Note:

module_function: defines #mismatched_return? (visibility: private)

Whether YARD return mismatches expected inferred/external type.

Silences when expected is fallback (uncertain).

Parameters:

  • ctx (Hash<Symbol, Object>)

Returns:

  • (Boolean)


2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 2073

def mismatched_return?(ctx)
  yard, expected, fallback = mismatched_return_types(ctx)
  return false unless yard && expected
  return false if expected_suppressed?(expected, fallback)

  method_name = extract_method_name(ctx)
  return false if yard_compatible?(yard, expected, fallback, method_name: method_name)
  return false if types_normalized_equal?(yard, expected)

  true
end

.mismatched_return_types(ctx) ⇒ (String?, String?, String)

Note:

module_function: defines #mismatched_return_types (visibility: private)

Extract yard/expected/fallback triple for return mismatch check.

Parameters:

  • ctx (Hash<Symbol, Object>)

Returns:

  • ((String?, String?, String))


2107
2108
2109
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 2107

def mismatched_return_types(ctx)
  [ctx[:info][:return_type], ctx[:normal_type], ctx[:config].fallback_type]
end

.missing_param?(pname, ctx) ⇒ Boolean

Note:

module_function: defines #missing_param? (visibility: private)

Parameters:

  • pname (String)
  • ctx (Hash<Symbol, Object>)

Returns:

  • (Boolean)


1072
1073
1074
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1072

def missing_param?(pname, ctx)
  !ctx[:info][:param_names].include?(pname)
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?)


1949
1950
1951
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1949

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) ⇒ Docscribe::Plugin::Context

Note:

module_function: defines #new_plugin_context (visibility: private)

New plugin context

Parameters:

  • insertion (Docscribe::InlineRewriter::Collector::Insertion)

    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:



2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 2385

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)


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

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

.normalize_type(type_str) ⇒ String

Note:

module_function: defines #normalize_type (visibility: private)

Normalize type string for comparison (unify RBS/YARD syntax).

Parameters:

  • type_str (String, nil)

Returns:

  • (String)


2234
2235
2236
2237
2238
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 2234

def normalize_type(type_str)
  s = type_str.to_s
  s = s.sub(/#.*\z/m, '').strip unless s.lstrip.start_with?('#')
  s.strip.squeeze(' ').gsub('[', '<').gsub(']', '>').gsub(/\buntyped\b/, 'Object').gsub(/\bFALLBACK_TYPE\b/, 'Object')
end

.normalized_equal?(yard, expected) ⇒ Boolean

Note:

module_function: defines #normalized_equal? (visibility: private)

Whether normalized types are equal.

Parameters:

  • yard (String?)
  • expected (String?)

Returns:

  • (Boolean)


2151
2152
2153
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 2151

def normalized_equal?(yard, expected)
  normalize_type(yard) == normalize_type(expected)
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)


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

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)


1850
1851
1852
1853
1854
1855
1856
1857
1858
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1850

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

.optional_normalized_equal?(yard, expected) ⇒ Boolean

Note:

module_function: defines #optional_normalized_equal? (visibility: private)

Whether optional-normalized types are equal.

Parameters:

  • yard (String?)
  • expected (String?)

Returns:

  • (Boolean)


2161
2162
2163
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 2161

def optional_normalized_equal?(yard, expected)
  normalize_type(yard).delete_suffix('?') == normalize_type(expected).delete_suffix('?')
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, String>, nil)

    hash map of parameter name to override type

Returns:

  • (String, nil)


1876
1877
1878
1879
1880
1881
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1876

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)


1262
1263
1264
1265
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1262

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)


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

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_needs_update?(ctx) ⇒ Boolean

Note:

module_function: defines #param_needs_update? (visibility: private)

Parameters:

  • ctx (Hash<Symbol, Object>)

Returns:

  • (Boolean)


1131
1132
1133
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1131

def param_needs_update?(ctx)
  should_validate_param?(ctx) || !!ctx[:external_sig]
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



1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1901

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

.param_type_changed?(pname, new_type, ctx) ⇒ Boolean

Note:

module_function: defines #param_type_changed? (visibility: private)

Parameters:

  • pname (String)
  • new_type (String, nil)
  • ctx (Hash<Symbol, Object>)

Returns:

  • (Boolean)


1182
1183
1184
1185
1186
1187
1188
1189
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1182

def param_type_changed?(pname, new_type, ctx)
  yard = ctx[:info][:param_types][pname]
  return false unless new_type && yard
  return false if normalize_type(yard) == normalize_type(new_type)
  return false if generic_compatible?(yard, new_type)

  yard != new_type
end

.parse_existing_doc_tags(lines) ⇒ Docscribe::InlineRewriter::DocBuilder::parseInfo

Note:

module_function: defines #parse_existing_doc_tags (visibility: private)

Parse existing doc tags

Parameters:

  • lines (Array<String>)

    existing doc comment lines

Returns:

  • (Docscribe::InlineRewriter::DocBuilder::parseInfo)

    parsed tag info



271
272
273
274
275
276
277
278
279
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 271

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 (Docscribe::InlineRewriter::DocBuilder::parseInfo)

    mutable parse info accumulator

  • tags_started (Boolean)

    whether @tags have been seen

Returns:

  • (Boolean)

    updated tags_started



352
353
354
355
356
357
358
359
360
361
362
363
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 352

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



776
777
778
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 776

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)


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

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 && desc.empty? ? nil : desc]
end

.record_invalid_return(lines, reasons, ctx) ⇒ void

Note:

module_function: defines #record_invalid_return (visibility: private)

This method returns an undefined value.

Record invalid return type.

Parameters:

  • lines (Array<String>)
  • reasons (Array<Hash<Symbol, Object>>)
  • ctx (Hash<Symbol, Object>)


2047
2048
2049
2050
2051
2052
2053
2054
2055
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 2047

def record_invalid_return(lines, reasons, ctx)
  yard = ctx[:info][:return_type]
  lines << "#{ctx[:indent]}# @return [#{ctx[:normal_type]}]\n"
  reasons << {
    type: :invalid_type,
    message: "invalid YARD type [#{yard}] for @return, expected [#{ctx[:normal_type]}]",
    source: 'syntax'
  }
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



2247
2248
2249
2250
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 2247

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 (Docscribe::Plugin::Tag)

    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



2318
2319
2320
2321
2322
2323
2324
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 2318

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



2259
2260
2261
2262
2263
2264
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 2259

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]}",
               source: ctx[:external_sig] ? 'rbs' : 'infer' }
end

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

Note:

module_function: defines #render_plugin_tags (visibility: private)

Render plugin tags

Parameters:

  • tags (Array<Docscribe::Plugin::Tag>)

    plugin tag objects

  • indent (String)

    indentation string for the doc line

Returns:

  • (Array<String>)


2417
2418
2419
2420
2421
2422
2423
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 2417

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) ⇒ Docscribe::InlineRewriter::DocBuilder::setup

Note:

module_function: defines #resolve_doc_setup! (visibility: private)

Resolve doc setup

Parameters:

  • setup (Docscribe::InlineRewriter::DocBuilder::setup)

    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:

  • (Docscribe::InlineRewriter::DocBuilder::setup)


191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 191

def resolve_doc_setup!(setup, node, name, config, opts)
  external_sig = resolve_external_sig(setup[:container], setup[:scope], name, opts[:signature_provider], node)
  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, node = nil) ⇒ 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

  • node (Parser::AST::Node) (defaults to: nil)

Returns:



227
228
229
230
231
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 227

def resolve_external_sig(container, scope, name, signature_provider, node = nil)
  param_count, param_names = extract_sig_param_info(node)
  signature_provider&.signature_for(container: container, scope: scope, name: name,
                                    param_count: param_count, param_names: param_names)
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)


1621
1622
1623
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1621

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)


2271
2272
2273
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 2271

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)


2405
2406
2407
2408
2409
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 2405

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

.should_validate_param?(ctx) ⇒ Boolean

Note:

module_function: defines #should_validate_param? (visibility: private)

Whether param validation should run via inferred/external types.

Parameters:

  • ctx (Hash<Symbol, Object>)

Returns:

  • (Boolean)


1156
1157
1158
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1156

def should_validate_param?(ctx)
  ctx[:config].respond_to?(:validate_types?) && ctx[:config].validate_types?
end

.should_validate_return?(ctx) ⇒ Boolean

Note:

module_function: defines #should_validate_return? (visibility: private)

Whether return validation should run via inferred types.

Parameters:

  • ctx (Hash<Symbol, Object>)

Returns:

  • (Boolean)


2062
2063
2064
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 2062

def should_validate_return?(ctx)
  ctx[:config].respond_to?(:validate_types?) && ctx[:config].validate_types?
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)


1610
1611
1612
1613
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1610

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 (Docscribe::InlineRewriter::DocBuilder::parseInfo)

    parse info hash



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

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 (Docscribe::InlineRewriter::DocBuilder::parseInfo)

    parse info hash



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

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

.types_normalized_equal?(yard, expected) ⇒ Boolean

Note:

module_function: defines #types_normalized_equal? (visibility: private)

Whether types are equal after normalization (including optional "?").

Parameters:

  • yard (String?)
  • expected (String?)

Returns:

  • (Boolean)


2141
2142
2143
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 2141

def types_normalized_equal?(yard, expected)
  normalized_equal?(yard, expected) || optional_normalized_equal?(yard, expected)
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)


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

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

.void_compatible?(yard, expected, fallback, method_name: nil) ⇒ Boolean

Note:

module_function: defines #void_compatible? (visibility: private)

Whether void YARD type is compatible with fallback union or initialize/setup dynamic.

Parameters:

  • yard (String, nil)
  • expected (String, nil)
  • fallback (String)
  • method_name (String, Symbol, nil) (defaults to: nil)

    method name for dynamic check

Returns:

  • (Boolean)


2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 2195

def void_compatible?(yard, expected, fallback, method_name: nil) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/MethodLength, Metrics/AbcSize
  return false unless normalize_type(yard) == 'void'

  return true if fallback_union?(expected, fallback) ||
                 %w[nil void].include?(normalize_type(expected))

  if method_name.to_s =~ /initialize|setup/
    norm = normalize_type(expected).delete_suffix('?').strip
    return true if norm == 'Hash' || norm.start_with?('Hash<') || norm.start_with?('Hash[')
    return true if %w[self Boolean].include?(norm)
  end

  if method_name.to_s.end_with?('?')
    norm = normalize_type(expected).delete_suffix('?').strip
    return true if norm == 'Boolean'
  end

  false
end

.yard_compatible?(yard, expected, fallback, method_name: nil) ⇒ Boolean

Note:

module_function: defines #yard_compatible? (visibility: private)

Whether yard type is compatible with expected via void/union/generic.

Parameters:

  • yard (String?)
  • expected (String?)
  • fallback (String)
  • method_name (String, Symbol, nil) (defaults to: nil)

    method name for void compatibility

Returns:

  • (Boolean)


2129
2130
2131
2132
2133
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 2129

def yard_compatible?(yard, expected, fallback, method_name: nil)
  void_compatible?(yard, expected, fallback, method_name: method_name) ||
    yard_in_expected_union?(yard, expected) ||
    generic_compatible?(yard, expected, method_name: method_name)
end

.yard_in_expected_union?(yard, expected) ⇒ Boolean

Note:

module_function: defines #yard_in_expected_union? (visibility: private)

Whether yard type is included in expected union (e.g. Boolean in Object, Boolean).

Parameters:

  • yard (String)
  • expected (String)

Returns:

  • (Boolean)


2182
2183
2184
2185
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 2182

def yard_in_expected_union?(yard, expected)
  normalized_yard = normalize_type(yard)
  expected.split(',').any? { |part| normalize_type(part) == normalized_yard }
end