module

Noir::GoCalleeExtractor

Tree-sitter-backed Go 1-hop callee extractor. Parallels Noir::PythonCalleeExtractor but works at the AST level — Go can't share the Python convention of "give me a body string", because tree-sitter Go needs a complete source_file and a bare function body isn't one.

The extractor receives a full Go file plus the set of route call expression rows the analyzer cares about. For each match it locates the handler argument and walks the appropriate body:

  • func_literal (inline closure handler) — walk the closure's body in place; path/line on emitted callees point at the original file.
  • identifier (named handler) — look the name up in the file's top-level function_declarations first, then in external_functions (sibling files in the same Go package). The external map is built once per directory by GoEngine#collect_package_function_bodies so cross-file lookups are cheap.
  • selector_expression — resolve unambiguous same-package method values (handler.Get) through external_methods, and imported top-level function handlers (pkg.Foo) when the analyzer supplies a go.mod-backed import-path function index.

Builtins (len, make, append, …) and Go's primitive type constructors (int, string, byte, …) are filtered to keep the per-endpoint list focused on signal that's actually useful to an AI reviewer.

Constants

BUILTINS = Set {"len", "cap", "make", "new", "append", "copy", "delete", "close", "panic", "recover", "print", "println", "string", "int", "int8", "int16", "int32", "int64", "uint", "uint8", "uint16", "uint32", "uint64", "uintptr", "byte", "rune", "float32", "float64", "complex64", "complex128", "complex", "bool", "error"}

Go builtins and primitive type-conversions that carry no useful signal. Anything framework-specific (c.JSON, c.Query, gin.H{...}, etc.) is kept on purpose — those tell a reviewer how the endpoint shapes input/output.

Instance methods

callees_for_routes(source : String, file_path : String, route_rows : Set(Int32), external_functions : Hash(String, FunctionBody), external_methods : Hash(String, Array(FunctionBody)) = Hash(String, Array(FunctionBody)).new, imported_functions : Hash(String, Hash(String, FunctionBody)) = Hash(String, Hash(String, FunctionBody)).new, imported_methods : Hash(String, Hash(String, Array(FunctionBody))) = Hash(String, Hash(String, Array(FunctionBody))).new)

For each call_expression at a row in route_rows, find the handler argument, walk its body, and return the 1-hop callees keyed by row. Each entry is a tuple {name, callee_file_path, file_line_1_based}.

external_methods maps a (package-unqualified) method name to the bodies that define it, so a method-value handler (as.Campaigns, s.handleOIDCRedirect — the dominant shape in gorilla/mux and chi apps) resolves to its method body when the name is unambiguous.

Source
callees_for_routes_if(enabled : Bool, source : String, file_path : String, route_rows : Set(Int32), external_functions : Hash(String, FunctionBody), external_methods : Hash(String, Array(FunctionBody)) = Hash(String, Array(FunctionBody)).new, imported_functions : Hash(String, Hash(String, FunctionBody)) = Hash(String, Hash(String, FunctionBody)).new, imported_methods : Hash(String, Hash(String, Array(FunctionBody))) = Hash(String, Hash(String, Array(FunctionBody))).new)

Like callees_for_routes, but returns an empty map immediately when enabled is false. Lets analyzers skip the tree-sitter walk on default scans where callees won't be observed.

Source
callees_in_body(fn : FunctionBody, external_functions : Hash(String, FunctionBody) = Hash(String, FunctionBody).new) : Array(Tuple(String, String, Int32))

Public entry for walking a captured function/method body and returning its 1-hop callees. Used by analyzers (Beego controller routing) that resolve a handler to a FunctionBody outside the standard route-row flow.

Source
collect_function_bodies(source : String, file_path : String) : Hash(String, FunctionBody)

Returns top-level function declarations in source, keyed by name. file_path is recorded on each FunctionBody so callees emitted by later re-parsing can report a useful path.

Callers treat the result as read-only (they copy entries into their own per-directory maps), which is what lets it be shared.

Source
collect_method_bodies(source : String, file_path : String) : Hash(String, Array(FunctionBody))

Collects top-level method_declaration bodies keyed by method name. The value is a list because a name can be defined on several receiver types in one package; callers that need an unambiguous resolution should require size == 1. Used to attach callees to controller-style routes whose handler is referenced by method name only.

Source
function_bodies_for_directory(package_bodies : Hash(String, Hash(String, FunctionBody)), dir : String) : Hash(String, FunctionBody)

Returns the cross-file function-body map for the given directory, or an empty map. Mirrors GoEngine#ts_function_bodies_for_directory.

Source
method_bodies_for_directory(package_method_bodies : Hash(String, Hash(String, Array(FunctionBody))), dir : String) : Hash(String, Array(FunctionBody))

Returns the per-directory method-body map, or an empty map.

Source
package_function_bodies(file_contents : Hash(String, String)) : Hash(String, Hash(String, FunctionBody))

Walk every cached .go source in file_contents and collect top-level function_declaration nodes into a per-directory map so cross-file identifier-handler resolution is O(1) at lookup time. Keyed by directory because Go's name resolution is scoped to a single package (== single directory). Module-level twin of GoEngine#collect_package_function_bodies for analyzers (Chi) that don't inherit from GoEngine.

Source
package_function_bodies_if(enabled : Bool, file_contents : Hash(String, String)) : Hash(String, Hash(String, FunctionBody))

Like package_function_bodies, but returns an empty map immediately when enabled is false. Module-level twin of the GoEngine#collect_package_function_bodies gate for analyzers that don't inherit from GoEngine.

Source
package_method_bodies_if(enabled : Bool, file_contents : Hash(String, String)) : Hash(String, Hash(String, Array(FunctionBody)))

Per-directory {method_name => [FunctionBody, ...]} map so a method-value handler (as.Campaigns, ctrl.Index) can be resolved to its method body for callee extraction. Module-level twin of GoEngine#collect_package_controller_method_bodies for analyzers (Chi) that don't inherit from GoEngine. Returns an empty map immediately when enabled is false so default scans pay nothing.

Source

Nested types