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
PARAM_BUILDERS =
{
  arg: lambda { |arg_node, indent, external_sig, param_types_override, **opts|
    [build_arg_line(arg_node, indent, external_sig, param_types_override, **opts)]
  },
  optarg: lambda { |arg_node, indent, external_sig, param_types_override, **opts|
    build_optarg_lines(arg_node, indent, external_sig, param_types_override, **opts)
  },
  kwarg: lambda { |arg_node, indent, external_sig, param_types_override, **opts|
    [build_kwarg_line(arg_node, indent, external_sig, param_types_override, **opts)]
  },
  kwoptarg: lambda { |arg_node, indent, external_sig, param_types_override, **opts|
    [build_kwoptarg_line(arg_node, indent, external_sig, param_types_override, **opts)]
  },
  restarg: lambda { |arg_node, indent, external_sig, param_types_override, **opts|
    [build_restarg_line(arg_node, indent, external_sig, param_types_override, **opts)]
  },
  kwrestarg: lambda { |arg_node, indent, external_sig, param_types_override, **opts|
    [build_kwrestarg_line(arg_node, indent, external_sig, param_types_override, **opts)]
  },
  blockarg: lambda { |arg_node, indent, external_sig, param_types_override, **opts|
    [build_blockarg_line(arg_node, indent, external_sig, param_types_override, **opts)]
  },
  forward_arg: ->(*) { [] } #: Array[String]
}.freeze

Class Method Summary collapse

Class Method Details

.add_missing_private(lines, reasons, ctx) ⇒ void

Note:

module_function: when included, also defines #add_missing_private (instance visibility: private)

This method returns an undefined value.

Add @private tag if missing.

Parameters:

  • lines (Array)
  • reasons (Array)
  • ctx (Hash)


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

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: when included, also defines #add_missing_protected (instance visibility: private)

This method returns an undefined value.

Add @protected tag if missing.

Parameters:

  • lines (Array)
  • reasons (Array)
  • ctx (Hash)


766
767
768
769
770
771
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 766

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: when included, also defines #append_assemble_body_lines (instance visibility: private)

This method returns an undefined value.

Append body lines to a doc line array.

Parameters:

  • line_ary (Array<String>)
  • ctx (Hash)
  • indent (Object)

    indentation string for doc comment lines

  • setup (Object)

    method setup hash with name, types, scope



935
936
937
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 935

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: when included, also defines #append_merge_tag_lines (instance visibility: private)

This method returns an undefined value.

Append merge tag lines into line_ary.

Parameters:

  • line_ary (Array<String>)
  • ctx (Hash)


368
369
370
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 368

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

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

Note:

module_function: when included, also defines #append_option_lines (instance visibility: private)

This method returns an undefined value.

Append @option lines for hash defaults.

Parameters:

  • lines (Array)
  • default (Object)
  • indent (String)
  • pname (String)
  • fallback_type (Object)


1392
1393
1394
1395
1396
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1392

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

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

Note:

module_function: when included, also defines #assemble_doc_lines (instance visibility: private)

Assemble all doc lines into a single array.

Parameters:

  • indent (String)

    indent

  • setup (Hash)

    setup

  • ctx (Hash)

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

Returns:

  • (Array<String>)


915
916
917
918
919
920
921
922
923
924
925
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 915

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

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

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

Note:

module_function: when included, also defines #build (instance visibility: private)

Build a complete doc block for one collected method insertion.

External signatures, when available, override inferred param and return types.

Parameters:

Returns:

  • (String, nil)

Raises:

  • (StandardError)


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

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: when included, also defines #build_all_body_tags (instance visibility: private)

Build all body tag lines for a doc block.

Parameters:

  • ctx (Hash)
  • indent (Object)

    indentation string for doc comment lines

  • setup (Object)

    method setup hash with name, types, scope

Returns:

  • (Array<String>)


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

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

.build_all_merge_tags(ctx) ⇒ Array<String>

Note:

module_function: when included, also defines #build_all_merge_tags (instance visibility: private)

Build an array of all merge tag lines.

Parameters:

  • ctx (Hash)

Returns:

  • (Array<String>)


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

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, external_sig, param_types_override, config) ⇒ Array<String>?

Note:

module_function: when included, also defines #build_all_param_lines (instance visibility: private)

Build all param lines for args.

Parameters:

  • args (Object)
  • indent (String)
  • external_sig (Object)
  • param_types_override (Object)
  • config (Docscribe::Config)

Returns:

  • (Array<String>, nil)


880
881
882
883
884
885
886
887
888
889
890
891
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 880

def build_all_param_lines(args, indent, external_sig, param_types_override, config)
  fb = config.fallback_type
  tk = config.treat_options_keyword_as_hash?
  ts = config.param_tag_style
  pd = config.include_param_documentation? ? config.param_documentation : ''
  params = (args.children || []).each_with_object([]) do |a, p|
    p.concat(build_param_line(a, indent, external_sig, param_types_override,
                              fallback_type: fb, treat_options_keyword_as_hash: tk,
                              param_documentation: pd, param_tag_style: ts))
  end
  params.empty? ? nil : params
end

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

Note:

module_function: when included, also defines # (instance visibility: private)

Build a param line for a required argument.

Parameters:

  • indent (Object)

    indentation string for doc comment lines

  • external_sig (Object)

    external method signature for type overrides

  • param_types_override (Object)

    map of parameter name to override type

  • arg_node (Object)

    AST node for the required argument

  • opts (Hash)

    additional options for param formatting

Returns:

  • (Object)


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

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

Note:

module_function: when included, also defines # (instance visibility: private)

Build a param line for a block argument (&block).

Parameters:

  • indent (Object)

    indentation string for doc comment lines

  • external_sig (Object)

    external method signature for type overrides

  • param_types_override (Object)

    map of parameter name to override type

  • arg_node (Object)

    AST node for the block argument (&block)

  • opts (Hash)

    additional options for param formatting

Returns:

  • (Object)


1317
1318
1319
1320
1321
1322
1323
1324
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1317

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

Note:

module_function: when included, also defines #build_debug_location (instance visibility: private)

Build a human-readable location string for debug output. Formats as “file.rb:line Container#method” for error reporting.

Parameters:

  • insertion (Object)

    the collected method insertion object

  • name (Object)

    the method name string

Returns:

  • (Object)


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

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) ⇒ Array<String>

Note:

module_function: when included, also defines #build_default_msg_lines (instance visibility: private)

Build default message lines for a doc block.

Parameters:

Returns:

  • (Array<String>)


1054
1055
1056
1057
1058
1059
1060
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1054

def build_default_msg_lines(indent, config, scope, visibility)
  if config.include_default_message?
    ["#{indent}# #{config.default_message(scope, visibility)}", "#{indent}#"]
  else
    []
  end
end

.build_doc_lines(setup, config:, **kwargs) ⇒ Object

Note:

module_function: when included, also defines #build_doc_lines (instance visibility: private)

Build doc lines for a full doc block. Delegates to assemble_doc_lines with setup and context.

Parameters:

  • setup (Object)

    method setup hash with indent, name, types, scope

  • config (Object)

    Docscribe configuration object

  • kwargs (Hash)

    additional keyword args including insertion, params_lines, raise_types, override_tags

Returns:

  • (Object)


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

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

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

Note:

module_function: when included, also defines #build_header_lines (instance visibility: private)

Build header line(s) for a doc block.

Parameters:

  • indent (String)
  • config (Docscribe::Config)
  • opts (Hash)

    additional options including container, method_symbol, name, normal_type

Returns:

  • (Array<String>)


1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1034

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: when included, also defines #build_initial_line_ary (instance visibility: private)

Build initial line array for merge dest lines.

Parameters:

  • existing_lines (Array<String>)
  • indent (String)

Returns:

  • (Array<String>)


334
335
336
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 334

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

Note:

module_function: when included, also defines # (instance visibility: private)

Build a param line for a keyword argument.

Parameters:

  • indent (Object)

    indentation string for doc comment lines

  • external_sig (Object)

    external method signature for type overrides

  • param_types_override (Object)

    map of parameter name to override type

  • arg_node (Object)

    AST node for the keyword argument

  • opts (Hash)

    additional options for param formatting

Returns:

  • (Object)


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

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

Note:

module_function: when included, also defines # (instance visibility: private)

Build a param line for an optional keyword argument.

Parameters:

  • indent (Object)

    indentation string for doc comment lines

  • external_sig (Object)

    external method signature for type overrides

  • param_types_override (Object)

    map of parameter name to override type

  • arg_node (Object)

    AST node for the optional keyword argument

  • opts (Hash)

    additional options for param formatting

Returns:

  • (Object)


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

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

Note:

module_function: when included, also defines # (instance visibility: private)

Build a param line for a keyword rest argument (**kwargs).

Parameters:

  • indent (Object)

    indentation string for doc comment lines

  • external_sig (Object)

    external method signature for type overrides

  • param_types_override (Object)

    map of parameter name to override type

  • arg_node (Object)

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

  • opts (Hash)

    additional options for param formatting

Returns:

  • (Object)


1300
1301
1302
1303
1304
1305
1306
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1300

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: when included, also defines #build_merge_additions (instance visibility: private)

Build only the missing doc lines that should be merged into an existing doc-like block.

This is used by safe mode for non-destructive updates.

Parameters:

Returns:

  • (String, nil)

Raises:

  • (StandardError)


121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 121

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

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

.build_missing_merge_result(insertion, existing_lines:, config:, **options) ⇒ Hash

Note:

module_function: when included, also defines #build_missing_merge_result (instance visibility: private)

Build structured missing-line information for safe merge mode.

Returns both:

  • generated missing lines

  • structured reasons used by ‘–explain`

Parameters:

Returns:

  • (Hash)

Raises:

  • (StandardError)


147
148
149
150
151
152
153
154
155
156
157
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 147

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:

also defines #build_module_function_note_lines (instance: private)

Note:

module_function: when included, also defines # (instance visibility: private)

Build module_function note line(s) for a full doc block.

Parameters:

Returns:

  • (Array<String>)


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

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: when included, also defines ##{name} " \
   "(instance visibility: #{included_vis})"]
end

.build_optarg_lines(arg_node, indent, external_sig, param_types_override, **opts) ⇒ Object

Note:

module_function: when included, also defines # (instance visibility: private)

Build param lines for an optional argument (including @option lines).

Parameters:

  • indent (Object)

    indentation string for doc comment lines

  • external_sig (Object)

    external method signature for type overrides

  • param_types_override (Object)

    map of parameter name to override type

  • arg_node (Object)

    AST node for the optional argument

  • opts (Hash)

    additional options for param formatting

Returns:

  • (Object)


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

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

Note:

module_function: when included, also defines # (instance visibility: private)

Build an @option line from a hash pair node.

Parameters:

  • pair (Object)

    AST pair node containing key and value

  • indent (Object)

    indentation string for the doc line

  • pname (Object)

    the parent parameter name for @option scope

  • fallback_type (Object)

    default type string when inference fails

Returns:

  • (Object)


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

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

Note:

module_function: when included, also defines # (instance visibility: private)

Build param types, param lines, and raise types for doc block.

Parameters:

Returns:

  • (Array)


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

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

Note:

module_function: when included, also defines #build_param_line (instance visibility: private)

Build a param line for a single argument node. Dispatches to the appropriate builder via PARAM_BUILDERS by arg type.

Parameters:

  • arg_node (Object)

    AST node for the argument

  • indent (Object)

    indentation string for doc comment lines

  • external_sig (Object)

    external method signature for type overrides

  • param_types_override (Object)

    map of parameter name to override type

  • opts (Hash)

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

Returns:

  • (Object)


1021
1022
1023
1024
1025
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1021

def build_param_line(arg_node, indent, external_sig, param_types_override, **opts)
  PARAM_BUILDERS.fetch(arg_node.type, lambda { |*|
    [] #: Array[String]
  }).call(arg_node, indent, external_sig, param_types_override, **opts)
end

.build_param_types_from_node(node, external_sig:, config:) ⇒ Hash{String => String}?

Note:

module_function: when included, also defines #build_param_types_from_node (instance visibility: private)

Build a param name => type map from a method node.

Parameters:

  • node (Parser::AST::Node)

    def or defs node

  • external_sig (Object, nil)

    external signature if available

  • config (Docscribe::Config)

Returns:

  • (Hash{String => String}, nil)


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

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:, param_types_override: nil) ⇒ Array<String>?

Note:

module_function: when included, also defines #build_params_lines (instance visibility: private)

Build generated ‘@param` / `@option` lines for a method node.

External signatures take precedence over inferred parameter types.

Parameters:

Returns:

  • (Array<String>, nil)


864
865
866
867
868
869
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 864

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

  build_all_param_lines(args, indent, external_sig, param_types_override, config)
end

.build_plugin_context(insertion, normal_type:) ⇒ Docscribe::Plugin::Context

Note:

module_function

Note:

module_function: when included, also defines #build_plugin_context (instance visibility: private)

Build a Plugin::Context from a collected insertion.

Parameters:

Returns:

Raises:

  • (StandardError)


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

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: when included, also defines #build_plugin_tag_lines (instance visibility: private)

Build plugin tag lines for a full doc block.

Parameters:

Returns:

  • (Array<String>)


1152
1153
1154
1155
1156
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1152

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: when included, also defines #build_raise_tag_lines (instance visibility: private)

Build raise tag lines for a full doc block.

Parameters:

Returns:

  • (Array<String>)


1108
1109
1110
1111
1112
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1108

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: when included, also defines #build_rescue_return_lines (instance visibility: private)

Build rescue conditional return lines for a full doc block.

Parameters:

Returns:

  • (Array<String>)


1136
1137
1138
1139
1140
1141
1142
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1136

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

Note:

module_function: when included, also defines # (instance visibility: private)

Build a param line for a rest argument (*args).

Parameters:

  • indent (Object)

    indentation string for doc comment lines

  • external_sig (Object)

    external method signature for type overrides

  • param_types_override (Object)

    map of parameter name to override type

  • arg_node (Object)

    AST node for the rest argument (*args)

  • opts (Hash)

    additional options for param formatting

Returns:

  • (Object)


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

def build_restarg_line(arg_node, indent, external_sig, param_types_override, **opts)
  pname = (arg_node.children.first || 'args').to_s
  ty = if external_sig&.rest_positional&.element_type
         "Array<#{external_sig.rest_positional.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) ⇒ Array<String>

Note:

module_function: when included, also defines #build_return_line_if_needed (instance visibility: private)

Build return tag line if emit condition is met.

Parameters:

  • config (Docscribe::Config)
  • indent (Object)

    indentation string for doc comment lines

  • setup (Object)

    method setup hash with name, normal_type, scope, visibility

Returns:

  • (Array<String>)


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

def build_return_line_if_needed(indent, setup, config)
  emit_ret = config.emit_return_tag?(setup[:scope], setup[:visibility])
  ret_line = build_return_tag_line(indent, setup[:normal_type], config, setup[:scope], setup[:visibility])
  emit_ret && ret_line ? [ret_line] : []
end

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

Note:

module_function: when included, also defines #build_return_tag_line (instance visibility: private)

Build return tag line for a full doc block.

Parameters:

  • indent (String)
  • normal_type (String)
  • config (Docscribe::Config)
  • scope (Symbol)
  • visibility (Symbol)

Returns:

  • (String, nil)


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

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: when included, also defines # (instance visibility: private)

Build without rescue wrapping (extracted for metric reduction).

Parameters:

Returns:

  • (String, nil)


182
183
184
185
186
187
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 182

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])
  lines.map { |l| "#{l}\n" }.join
end

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

Note:

module_function: when included, also defines #build_visibility_tag_lines (instance visibility: private)

Build visibility tag line(s) for a full doc block.

Parameters:

Returns:

  • (Array<String>)


1069
1070
1071
1072
1073
1074
1075
1076
1077
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1069

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

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

.collect_all_missing(setup, info, insertion, config, options) ⇒ Hash

Note:

module_function: when included, also defines #collect_all_missing (instance visibility: private)

Collect all missing doc elements and return { lines:, reasons: }. Delegates to collect_missing_all with a merged context hash.

Parameters:

  • setup (Object)

    resolved setup hash with node, name, indent, types

  • info (Object)

    parsed existing doc tag information

  • insertion (Object)

    the collected method insertion object

  • config (Object)

    Docscribe configuration object

  • options (Object)

    additional options hash forwarded to missing collector

Returns:

  • (Hash)


416
417
418
419
420
421
422
423
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 416

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: when included, also defines #collect_all_param_types (instance visibility: private)

This method returns an undefined value.

Collect param types for all args using dispatch hash.

Parameters:

  • args (Object)
  • param_types (Hash)
  • external_sig (Object)
  • config (Object)


572
573
574
575
576
577
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 572

def collect_all_param_types(args, param_types, external_sig, config)
  (args.children || []).each do |a|
    collector = PARAM_TYPE_COLLECTORS[a.type]
    collector&.call(a, param_types, external_sig, config)
  end
end

.collect_missing_all(ctx) ⇒ Hash

Note:

module_function: when included, also defines #collect_missing_all (instance visibility: private)

Collect all missing elements via context hash.

Parameters:

  • ctx (Hash)

Returns:

  • (Hash)


430
431
432
433
434
435
436
437
438
439
440
441
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 430

def collect_missing_all(ctx)
  lines = [] #: Array[String]
  reasons = [] #: Array[Hash]
  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:

also defines #collect_missing_module_function_note! (instance: private)

Note:

module_function: when included, also defines # (instance visibility: private)

This method returns an undefined value.

Collect missing module_function note for build_missing_merge_result.

Parameters:

  • lines (Array<String>)
  • reasons (Array<Hash>)
  • ctx (Hash)


781
782
783
784
785
786
787
788
789
790
791
792
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 781

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: when included, also defines ##{ctx[:name]} " \
           "(instance 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: when included, also defines #collect_missing_params! (instance visibility: private)

This method returns an undefined value.

Collect missing/updated param lines for build_missing_merge_result.

Parameters:

  • lines (Array<String>)
  • reasons (Array<Hash>)
  • ctx (Hash)


801
802
803
804
805
806
807
808
809
810
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 801

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: when included, also defines #collect_missing_plugin_tags! (instance visibility: private)

This method returns an undefined value.

Collect missing plugin tags for build_missing_merge_result.

Parameters:

  • lines (Array<String>)
  • reasons (Array<Hash>)
  • ctx (Hash)


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

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: when included, also defines #collect_missing_raises! (instance visibility: private)

This method returns an undefined value.

Collect missing raise tags for build_missing_merge_result.

Parameters:

  • lines (Array<String>)
  • reasons (Array<Hash>)
  • ctx (Hash)


1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1501

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:

also defines #collect_missing_rescue_returns! (instance: private)

Note:

module_function: when included, also defines # (instance visibility: private)

This method returns an undefined value.

Collect missing rescue conditional returns for build_missing_merge_result.

Parameters:

  • lines (Array<String>)
  • reasons (Array<Hash>)
  • ctx (Hash)


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

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: when included, also defines #collect_missing_return! (instance visibility: private)

This method returns an undefined value.

Collect missing/updated return tag for build_missing_merge_result.

Parameters:

  • lines (Array<String>)
  • reasons (Array<Hash>)
  • ctx (Hash)


1521
1522
1523
1524
1525
1526
1527
1528
1529
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1521

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

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

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

Note:

module_function: when included, also defines #collect_missing_visibility! (instance visibility: private)

This method returns an undefined value.

Collect missing visibility tag for build_missing_merge_result.

Parameters:

  • lines (Array<String>)
  • reasons (Array<Hash>)
  • ctx (Hash)


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

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

Note:

module_function: when included, also defines # (instance visibility: private)

Collect param type for an optional/keyword optional argument.

Parameters:

  • param_types (Object)

    hash accumulating parameter name-to-type mappings

  • external_sig (Object)

    external method signature for type overrides

  • config (Object)

    Docscribe configuration for fallback type options

  • infer_name (Object)

    lambda to transform parameter name for inference

  • arg_node (Object)

    AST node for the optional/keyword optional argument

Returns:

  • (Object)


607
608
609
610
611
612
613
614
615
616
617
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 607

def collect_optarg_param_type(arg_node, param_types, external_sig, config, infer_name:)
  pname, default = *arg_node
  pname = pname.to_s
  default_src = source_from_node(default)
  infer_pname = resolve_infer_name(pname, infer_name)
  ty = 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?)
  param_types[pname] = ty
end

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

Note:

module_function: when included, also defines # (instance visibility: private)

Collect a single param line for build_missing_merge_result.

Parameters:

  • lines (Object)

    array of output doc lines being accumulated

  • reasons (Object)

    array of reason hashes for –explain output

  • ctx (Object)

    merged context hash with build parameters

  • param_line (Object)

    a single @param tag line to evaluate

Returns:

  • (Object)


820
821
822
823
824
825
826
827
828
829
830
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 820

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

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

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

Note:

module_function: when included, also defines # (instance visibility: private)

Collect param type for a required/keyword argument.

Parameters:

  • param_types (Object)

    hash accumulating parameter name-to-type mappings

  • external_sig (Object)

    external method signature for type overrides

  • config (Object)

    Docscribe configuration for fallback type options

  • infer_name (Object)

    lambda to transform parameter name for inference

  • arg_node (Object)

    AST node for the required/keyword argument

Returns:

  • (Object)


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

def collect_param_type(arg_node, param_types, external_sig, config, infer_name:)
  pname = arg_node.children.first.to_s
  infer_pname = resolve_infer_name(pname, infer_name)
  ty = 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?)
  param_types[pname] = ty
end

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

Note:

module_function: when included, also defines # (instance visibility: private)

Collect an updated param line.

Parameters:

  • pname (Object)

    the parameter name string

  • lines (Object)

    array of output doc lines being accumulated

  • reasons (Object)

    array of reason hashes for –explain output

  • ctx (Object)

    merged context hash with build parameters

  • param_line (Object)

    a single @param tag line to evaluate

Returns:

  • (Object)


841
842
843
844
845
846
847
848
849
850
851
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 841

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

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

.compute_returns_spec(node, config, param_types, core_rbs_provider) ⇒ Hash

Note:

module_function: when included, also defines #compute_returns_spec (instance visibility: private)

Compute returns_spec from node.

Parameters:

  • node (Parser::AST::Node)
  • config (Docscribe::Config)
  • param_types (Hash, nil)
  • core_rbs_provider (Object, nil)

Returns:

  • (Hash)


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

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

.core_body_tags(indent, setup, ctx) ⇒ Array

Note:

module_function: when included, also defines #core_body_tags (instance visibility: private)

Core body tags without optional params_lines.

Parameters:

  • ctx (Hash)
  • indent (Object)

    indentation string for doc comment lines

  • setup (Object)

    method setup hash with name, types, scope

Returns:

  • (Array)


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

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

.debug?Boolean

Note:

module_function: when included, also defines #debug? (instance visibility: private)

Check whether debug mode is enabled.

Returns:

  • (Boolean)


1654
1655
1656
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1654

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

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

Note:

module_function: when included, also defines #debug_warn (instance visibility: private)

This method returns an undefined value.

Print a debug warning for a failed doc build phase.

Parameters:

  • error (StandardError)

    the error that occurred

  • insertion (Collector::Insertion)

    the method insertion being processed

  • name (String)

    the method name

  • phase (String)

    the processing phase



1626
1627
1628
1629
1630
1631
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1626

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) ⇒ Array<String>

Note:

module_function: when included, also defines #defaults_and_visibility (instance visibility: private)

Build default msg and visibility tags.

Parameters:

  • config (Object)
  • scope (Symbol)
  • visibility (Symbol)
  • indent (Object)

    indentation string for doc comment lines

Returns:

  • (Array<String>)


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

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

.doc_setup(insertion, config:, **opts) ⇒ Hash?

Note:

module_function: when included, also defines #doc_setup (instance visibility: private)

Shared document setup extraction for all build methods.

Parameters:

Returns:

  • (Hash, nil)


166
167
168
169
170
171
172
173
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 166

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

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

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

Note:

module_function: when included, also defines # (instance visibility: private)

Extract args sub-node from a def or defs node.

Parameters:

  • node (Parser::AST::Node)

Returns:

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


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

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

.extract_base_setup(insertion, name) ⇒ Hash

Note:

module_function: when included, also defines #extract_base_setup (instance visibility: private)

Extract base node metadata.

Parameters:

Returns:

  • (Hash)


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

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

.extract_param_info(line, param_names, param_types) ⇒ Object

Note:

module_function: when included, also defines #extract_param_info (instance visibility: private)

Extract param info from a doc line. Parses @param lines and populates param_names and param_types hashes.

Parameters:

  • line (Object)

    a single doc comment line to parse

  • param_names (Object)

    hash tracking existing @param names

  • param_types (Object)

    hash tracking existing @param types

Returns:

  • (Object)


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

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

  param_names[pname] = true
  unless (type_match = line.match(/@param\s+\[([^\]]+)\]\s+\S+/) || line.match(/@param\s+\S+\s+\[([^\]]+)\]/))
    return
  end

  param_types[pname] = type_match[1] || 'untyped'
end

.extract_param_name_from_param_line(line) ⇒ String?

Note:

also defines #extract_param_name_from_param_line (instance: private)

Note:

module_function: when included, also defines # (instance visibility: private)

Extract the parameter name from a ‘@param` doc line.

Handles both ‘“@param [Type] name”` and `“@param name [Type]”` styles.

Parameters:

  • line (String)

    a ‘@param` doc line

Returns:

  • (String, nil)

    the parameter name or nil



1475
1476
1477
1478
1479
1480
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1475

def extract_param_name_from_param_line(line)
  return Regexp.last_match(1) if line =~ /@param\b\s+\[[^\]]+\]\s+(\S+)/
  return Regexp.last_match(1) if line =~ /@param\b\s+(\S+)\s+\[[^\]]+\]/

  nil
end

.extract_param_type_from_param_line(line) ⇒ String?

Note:

also defines #extract_param_type_from_param_line (instance: private)

Note:

module_function: when included, also defines # (instance visibility: private)

Extract the type from a ‘@param` tag line.

Parameters:

  • line (String)

    a ‘@param` tag line

Returns:

  • (String, nil)


1488
1489
1490
1491
1492
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1488

def extract_param_type_from_param_line(line)
  if (m = line.match(/@param\s+\[([^\]]+)\]\s+\S+/) || line.match(/@param\s+\S+\s+\[([^\]]+)\]/))
    m[1]
  end
end

.extract_plugin_info(line, plugin_tags) ⇒ Object

Note:

module_function: when included, also defines #extract_plugin_info (instance visibility: private)

Extract plugin tag info from a doc line. Captures any @tag_name from the line into the plugin_tags hash.

Parameters:

  • line (Object)

    a single doc comment line to parse

  • plugin_tags (Object)

    hash tracking existing plugin tag names

Returns:

  • (Object)


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

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

Note:

module_function: when included, also defines #extract_raise_info (instance visibility: private)

Extract raise info from a doc line. Parses @raise tags and records exception types in raise_types hash.

Parameters:

  • line (Object)

    a single doc comment line to parse

  • raise_types (Object)

    hash tracking existing @raise types

Returns:

  • (Object)


498
499
500
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 498

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) ⇒ String, ...

Note:

module_function: when included, also defines #extract_raise_types_from_line (instance visibility: private)

Extract exception names from a ‘@raise` doc line.

Parameters:

  • line (String)

    a ‘@raise` doc line

Returns:

  • (String, nil)

    the exception name or nil

  • (Array)

    if StandardError or line not matched

Raises:

  • (StandardError)


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

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

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

.extract_return_info(line, info) ⇒ Object

Note:

module_function: when included, also defines #extract_return_info (instance visibility: private)

Extract return info from a doc line. Detects @return tags and records type and presence in info hash.

Parameters:

  • line (Object)

    a single doc comment line to parse

  • info (Object)

    parse info hash to update with return data

Returns:

  • (Object)


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

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

  info[:has_return] = true
  return unless (m = line.match(/@return\s+\[([^\]]+)\]/))

  info[:return_type] = m[1]
end

.extract_visibility_info(line, info) ⇒ Object

Note:

module_function: when included, also defines #extract_visibility_info (instance visibility: private)

Extract visibility info from a doc line. Detects @private, @protected, and @note module_function tags.

Parameters:

  • line (Object)

    a single doc comment line to parse

  • info (Object)

    parse info hash to update with visibility flags

Returns:

  • (Object)


485
486
487
488
489
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 485

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

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

Note:

module_function: when included, also defines #format_param_tag (instance visibility: private)

Format a YARD @param tag line with optional documentation text.

Parameters:

  • indent (Object)

    indentation string for the doc line

  • name (Object)

    the parameter name

  • type (Object)

    the parameter type string

  • documentation (Object)

    optional documentation text appended to the tag

  • style (Object)

    param tag style (:type_name or :name_type)

Returns:

  • (Object)


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

def format_param_tag(indent, name, type, documentation, style:)
  doc = documentation.to_s.strip
  type = type.to_s

  line = case style.to_s
         when 'name_type'
           "#{indent}# @param #{name} [#{type}]"
         else
           "#{indent}# @param [#{type}] #{name}"
         end

  doc.empty? ? line : "#{line} #{doc}"
end

.hash_option_pairs(node) ⇒ Object

Note:

module_function: when included, also defines #hash_option_pairs (instance visibility: private)

Extract hash option pairs from a default value node.

Parameters:

  • node (Object)

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

Returns:

  • (Object)


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

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

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

.init_parse_infoHash

Note:

module_function: when included, also defines #init_parse_info (instance visibility: private)

Initialize an empty parse info hash.

Returns:

  • (Hash)


289
290
291
292
293
294
295
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 289

def init_parse_info
  {
    param_names: {}, param_types: {}, raise_types: {}, plugin_tags: {},
    has_return: false, return_type: nil,
    has_private: false, has_protected: false, has_module_function_note: false
  }
end

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

Note:

module_function: when included, also defines # (instance visibility: private)

Three-tier type lookup: external_sig -> override -> inference.

Parameters:

  • external_sig (Object)

    external method signature for type overrides

  • param_types_override (Object)

    map of parameter name to override type

  • pname (Object)

    the parameter name string

  • infer_name (Object)

    parameter name string or transformed version for inference

  • opts (Hash)

    additional options including infer_default, fallback_type, treat_options_keyword_as_hash

Returns:

  • (Object)


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

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

Note:

module_function: when included, also defines # (instance visibility: private)

Two-tier type lookup: override -> inference (for rest/kwrest types).

Parameters:

  • param_types_override (Object)

    map of parameter name to override type

  • pname (Object)

    the parameter name string

  • infer_name (Object)

    parameter name string or transformed version for inference

  • fallback_type (Object)

    default type string when inference fails

  • treat_options_keyword_as_hash (Object)

    whether to treat options keyword as Hash type

Returns:

  • (Object)


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

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: when included, also defines #merge_all_tag_lines (instance visibility: private)

Merge all tag lines into a line array.

Parameters:

  • base_ary (Array<String>)
  • ctx (Hash)

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

Returns:

  • (Array<String>)


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

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

Note:

module_function: when included, also defines #merge_dest_lines (instance visibility: private)

Build merged destination lines for safe merge mode. Wrapper that delegates to merge_lines_with_context.

Parameters:

  • existing_lines (Object)

    existing doc comment lines to merge into

  • ctx (Hash)

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

Returns:

  • (Object)


304
305
306
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 304

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

.merge_lines_with_context(existing_lines, **ctx) ⇒ Object

Note:

module_function: when included, also defines #merge_lines_with_context (instance visibility: private)

Merge dest lines using a context hash (extracted for metric reduction).

Parameters:

  • existing_lines (Object)

    existing doc comment lines being merged

  • ctx (Hash)

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

Returns:

  • (Object)


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

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:

also defines #merge_module_function_note_lines (instance: private)

Note:

module_function: when included, also defines # (instance visibility: private)

Merge module_function note line for safe merge mode.

Parameters:

Returns:

  • (Array<String>)


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

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

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

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

Note:

module_function: when included, also defines #merge_param_lines (instance visibility: private)

Merge param lines for safe merge mode.

Parameters:

  • node (Parser::AST::Node)
  • indent (String)
  • config (Docscribe::Config)
  • opts (Hash)

    additional options including external_sig, param_types, info

Returns:

  • (Array<String>)


666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 666

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: when included, also defines #merge_raise_tag_lines (instance visibility: private)

Merge raise tag lines for safe merge mode.

Parameters:

Returns:

  • (Array<String>)


690
691
692
693
694
695
696
697
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 690

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: when included, also defines #merge_rescue_return_lines (instance visibility: private)

Merge rescue conditional return lines for safe merge mode.

Parameters:

Returns:

  • (Array<String>)


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

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: when included, also defines #merge_return_line (instance visibility: private)

This method returns an undefined value.

Merge return tag line into line_ary.

Parameters:

  • line_ary (Array<String>)
  • config (Object)
  • info (Object)
  • indent (Object)

    indentation string for doc comment lines

  • setup (Object)

    method setup hash with node, name, types, scope



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

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: when included, also defines #merge_return_tag_line (instance visibility: private)

Merge return tag line for safe merge mode.

Parameters:

  • indent (String)
  • normal_type (String)
  • config (Docscribe::Config)
  • opts (Hash)

    additional options including scope, visibility, info

Returns:

  • (String, nil)


707
708
709
710
711
712
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 707

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: when included, also defines #merge_tag_lines_core (instance visibility: private)

This method returns an undefined value.

Core tag line merging.

Parameters:

  • line_ary (Array<String>)
  • ctx (Hash)


357
358
359
360
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 357

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: when included, also defines #merge_visibility_tag_lines (instance visibility: private)

Merge visibility tag lines for safe merge mode.

Parameters:

Returns:

  • (Array<String>)


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

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

.new_plugin_context(insertion, node, source, normal_type) ⇒ Docscribe::Plugin::Context

Note:

module_function: when included, also defines #new_plugin_context (instance visibility: private)

Build a Plugin::Context from parts.

Parameters:

  • insertion (Object)
  • node (Object)
  • source (String)
  • normal_type (String)

Returns:



1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1680

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),
    inferred_params: {},
    inferred_return: normal_type,
    source: source
  )
end

.node_default_literal(node) ⇒ Object

Note:

module_function: when included, also defines #node_default_literal (instance visibility: private)

Extract the source text of a default value node.

Parameters:

  • node (Object)

    AST node whose source text to extract

Returns:

  • (Object)


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

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

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

Note:

module_function: when included, also defines #optarg_type (instance visibility: private)

Resolve optarg type.

Parameters:

  • pname (String)
  • default (Object)
  • external_sig (Object)
  • param_types_override (Object)
  • opts (Hash)

Returns:

  • (String)


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

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

Note:

module_function: when included, also defines #option_key_name (instance visibility: private)

Extract the option key name from a hash key node.

Parameters:

  • key_node (Object)

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

Returns:

  • (Object)


1434
1435
1436
1437
1438
1439
1440
1441
1442
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1434

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

.override_param_type_for(pname, override_map) ⇒ Object

Note:

module_function: when included, also defines #override_param_type_for (instance visibility: private)

Look up a parameter type from an override map.

Parameters:

  • pname (Object)

    the parameter name to look up

  • override_map (Object)

    hash map of parameter name to override type

Returns:

  • (Object)


1460
1461
1462
1463
1464
1465
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1460

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

.parse_existing_doc_tags(lines) ⇒ Hash

Note:

module_function: when included, also defines #parse_existing_doc_tags (instance visibility: private)

Parse existing doc comment lines and extract known YARD tags.

Extracts: ‘@param` names, `@return`, `@raise`, `@private`, `@protected`, `@module_function` notes, and `@option` lines.

Parameters:

  • lines (Array<String>)

    existing doc comment lines

Returns:

  • (Hash)

    parsed tag info



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

def parse_existing_doc_tags(lines)
  init = init_parse_info
  Array(lines).each_with_object(init) do |line, info|
    extract_param_info(line, info[:param_names], info[:param_types])
    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
end

.parse_raise_bracket_list(str) ⇒ Array<String>?

Note:

module_function: when included, also defines #parse_raise_bracket_list (instance visibility: private)

Parse exception names from a ‘@raise [ExceptionA, ExceptionB]` line.

Parameters:

  • str (Object)

    comma-separated exception names string from @raise brackets

Returns:

  • (Array<String>, nil)

    the exception names or nil



541
542
543
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 541

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

.record_missing_return(lines, reasons, ctx) ⇒ Object

Note:

module_function: when included, also defines #record_missing_return (instance visibility: private)

Record a missing @return tag and its reason.

Parameters:

  • lines (Object)

    array of output doc lines being accumulated

  • reasons (Object)

    array of reason hashes for –explain output

  • ctx (Object)

    merged context hash with normal_type and indent

Returns:

  • (Object)


1538
1539
1540
1541
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1538

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

Note:

module_function: when included, also defines #record_plugin_tag (instance visibility: private)

Record a missing plugin tag and its reason.

Parameters:

  • tag (Object)

    plugin tag object to render and record

  • lines (Object)

    array of output doc lines being accumulated

  • reasons (Object)

    array of reason hashes for –explain output

  • ctx (Object)

    merged context hash with info and indent

Returns:

  • (Object)


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

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

Note:

module_function: when included, also defines #record_updated_return (instance visibility: private)

Record an updated @return tag and its reason.

Parameters:

  • lines (Object)

    array of output doc lines being accumulated

  • reasons (Object)

    array of reason hashes for –explain output

  • ctx (Object)

    merged context hash with normal_type and info

Returns:

  • (Object)


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

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

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

Note:

module_function

Note:

module_function: when included, also defines #render_plugin_tags (instance visibility: private)

Render plugin tags as indented comment lines.

Parameters:

Returns:

  • (Array<String>)


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

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

.resolve_doc_setup!(setup, node, name, config, opts) ⇒ Hash

Note:

module_function: when included, also defines # (instance visibility: private)

Resolve external signature, returns spec, and normal type for doc setup.

Parameters:

  • setup (Hash)
  • node (Parser::AST::Node)
  • name (String)
  • config (Docscribe::Config)
  • opts (Hash)

Returns:

  • (Hash)


214
215
216
217
218
219
220
221
222
223
224
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 214

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

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

.resolve_external_sig(container, scope, name, signature_provider) ⇒ Object?

Note:

module_function: when included, also defines #resolve_external_sig (instance visibility: private)

Resolve external signature.

Parameters:

  • container (String)
  • scope (Symbol)
  • name (String)
  • signature_provider (Object, nil)

Returns:

  • (Object, nil)


247
248
249
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 247

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

.resolve_infer_name(pname, infer_name) ⇒ String

Note:

module_function: when included, also defines #resolve_infer_name (instance visibility: private)

Resolve the infer name string from a param name and infer_name lambda.

Parameters:

  • pname (String)
  • infer_name (Proc, nil)

Returns:

  • (String)


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

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

.return_type_changed?(ctx) ⇒ Object

Note:

module_function: when included, also defines #return_type_changed? (instance visibility: private)

Check if the return type changed between existing doc and inferred/signature type. Compares existing return type to the resolved normal type.

Parameters:

  • ctx (Object)

    merged context hash with external_sig, info, and normal_type

Returns:

  • (Object)


1562
1563
1564
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1562

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: when included, also defines #safe_node_source (instance visibility: private)

Safely extract source text from a node.

Parameters:

  • node (Parser::AST::Node)

Returns:

  • (String)

Raises:

  • (StandardError)


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

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

.source_from_node(node) ⇒ String?

Note:

module_function: when included, also defines #source_from_node (instance visibility: private)

Extract source text from an AST node.

Parameters:

  • node (Object)

Returns:

  • (String, nil)


1217
1218
1219
1220
# File 'lib/docscribe/inline_rewriter/doc_builder.rb', line 1217

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