GtBridge.Analysis.Source (gt_bridge v0.19.2)

Copy Markdown View Source

I am the pure source-text half of Analysis: function/type entry extraction (strict and lenient), module scoping for multi-module files, and the canonical source-edit splices (swap/replace/append). I never touch the code server; beam-side merging stays in GtBridge.Analysis.

Summary

Functions

I append new_text as a new function just before module's closing end, located from the parse so a sibling or nested module in the same file doesn't misdirect it. Returns source unchanged when module has no defmodule to append to (e.g. a typedstruct-generated module), or the source doesn't parse.

I return the alias/import/require statements ast declares — whole statements, so formatter-wrapped directives arrive intact. With no module I sweep the top level and every top-level module (buffer semantics); given a dotted module name I scope to that module's own body, so siblings in the same file don't leak theirs in.

I parse source and return the AST function entries (the same shape all_functions/1 returns minus the runtime-export merging, which needs the module to be loaded). Works on disk bytes alone, so safe to call before / after a failed compile.

I extract the top-level defmodule X.Y name from source. Returns the dotted module string, or nil when the source doesn't define one or doesn't parse.

I return every module source defines (nested defmodules and typedstruct module: children included) as dotted-name strings. Returns [] when the source doesn't parse.

I parse source with the options every source walk uses.

I replace the {name, arity} function within module in source with new_text (or remove it when new_text is empty), taking the range from source itself so the splice can't drift. Unknown name/arity returns source unchanged.

I swap two functions (by {name, arity}) within module in source, taking ranges from source itself so the splice can't drift. Unknown name/arity returns source unchanged.

Functions

append_function(source, module, new_text)

@spec append_function(String.t(), String.t(), String.t()) :: String.t()

I append new_text as a new function just before module's closing end, located from the parse so a sibling or nested module in the same file doesn't misdirect it. Returns source unchanged when module has no defmodule to append to (e.g. a typedstruct-generated module), or the source doesn't parse.

directives(ast, module \\ nil)

@spec directives(Macro.t(), String.t() | nil) :: [Macro.t()]

I return the alias/import/require statements ast declares — whole statements, so formatter-wrapped directives arrive intact. With no module I sweep the top level and every top-level module (buffer semantics); given a dotted module name I scope to that module's own body, so siblings in the same file don't leak theirs in.

functions_in_source(source)

@spec functions_in_source(String.t()) :: [map()]

I parse source and return the AST function entries (the same shape all_functions/1 returns minus the runtime-export merging, which needs the module to be loaded). Works on disk bytes alone, so safe to call before / after a failed compile.

module_in_source(source)

@spec module_in_source(String.t()) :: String.t() | nil

I extract the top-level defmodule X.Y name from source. Returns the dotted module string, or nil when the source doesn't define one or doesn't parse.

module_source_entries(source, module)

@spec module_source_entries(String.t(), String.t()) :: [map()]

modules_in_source(source)

@spec modules_in_source(String.t()) :: [String.t()]

I return every module source defines (nested defmodules and typedstruct module: children included) as dotted-name strings. Returns [] when the source doesn't parse.

quoted(source)

@spec quoted(String.t()) :: {:ok, Macro.t()} | {:error, term()}

I parse source with the options every source walk uses.

replace_function(source, module, name, arity, new_text)

@spec replace_function(String.t(), String.t(), String.t(), arity(), String.t()) ::
  String.t()

I replace the {name, arity} function within module in source with new_text (or remove it when new_text is empty), taking the range from source itself so the splice can't drift. Unknown name/arity returns source unchanged.

source_function_names(source, ast)

swap_functions(source, module, name_a, arity_a, name_b, arity_b)

@spec swap_functions(String.t(), String.t(), String.t(), arity(), String.t(), arity()) ::
  String.t()

I swap two functions (by {name, arity}) within module in source, taking ranges from source itself so the splice can't drift. Unknown name/arity returns source unchanged.