class
Analyzer::Go::GoEngine
- Analyzer::Go::GoEngine
- Analyzer
- Reference
- Object
Direct Known Subclasses
- Analyzer::Go::Beego
- Analyzer::Go::ConnectRpc
- Analyzer::Go::Echo
- Analyzer::Go::Fiber
- Analyzer::Go::Gf
- Analyzer::Go::Gin
- Analyzer::Go::GoRestful
- Analyzer::Go::Goyave
- Analyzer::Go::GoZero
- Analyzer::Go::Hertz
- Analyzer::Go::Huma
- Analyzer::Go::Iris
- Analyzer::Go::Mux
- Analyzer::Go::Pocketbase
Defined in:
analyzer/engines/go_engine.crConstant Summary
-
GO_HTTP_ROUTE_CALL_RE =
/\.(?:GET|POST|PUT|DELETE|PATCH|HEAD|OPTIONS|Get|Post|Put|Delete|Patch|Head|Options|ANY|Any|All)\s*\(/
Class Method Summary
-
.go_test_file?(path : String) : Bool
*_test.gois Go's hard-wired build-tag for test-only source.
Instance Method Summary
- #add_param_to_endpoint(param : Param, endpoint : Endpoint)
- #add_static_path_if_valid(static_path : Hash(String, String), public_dirs : Array(Hash(String, String)))
-
#collect_import_path_function_bodies(package_function_bodies : Hash(String, Hash(String, Noir::GoCalleeExtractor::FunctionBody))) : Hash(String, Hash(String, Noir::GoCalleeExtractor::FunctionBody))
Builds
{import_path => {function_name => body}}for local Go packages under the configured base paths. -
#collect_import_path_method_bodies(package_method_bodies : Hash(String, Hash(String, Array(Noir::GoCalleeExtractor::FunctionBody)))) : Hash(String, Hash(String, Array(Noir::GoCalleeExtractor::FunctionBody)))
Builds
{import_path => {method_name => [body, ...]}}for local Go packages under the configured base paths. -
#collect_package_controller_method_bodies(file_contents : Hash(String, String)) : Hash(String, Hash(String, Array(Noir::GoCalleeExtractor::FunctionBody)))
Per-directory
{method_name => [FunctionBody, ...]}map for controller-style routes whose handler is referenced by method name (Beego'sweb.Router("/x", &Ctrl{}, "get:Method")). -
#collect_package_controller_methods(file_contents : Hash(String, String)) : Hash(String, Hash(String, Array(String)))
--- Beego controller-method pre-pass --------------------------------
-
#collect_package_function_bodies(file_contents : Hash(String, String)) : Hash(String, Hash(String, Noir::GoCalleeExtractor::FunctionBody))
--- Cross-file function body pre-pass --------------------------------
-
#collect_package_groups_ts(group_method : String = "Group", import_marker : String | Nil = nil) : Tuple(Hash(String, Hash(String, String)), Hash(String, String))
--- Tree-sitter group/route pre-pass --------------------------------
-
#framework_package_dirs(file_contents : Hash(String, String), import_marker : String) : Set(String)
Per-package directories that import a target framework.
- #framework_route_source_candidate?(content : String, dir : String, framework_dirs : Set(String), import_marker : String, extra_methods : Array(String)) : Bool
-
#go_route_source_candidate?(content : String, extra_methods : Array(String)) : Bool
Cheap gate before the tree-sitter route pass.
-
#read_package_file_contents : Hash(String, String)
Read every
.gofile once into a{path => source}hash. - #resolve_public_dirs(public_dirs : Array(Hash(String, String)))
- #resolve_public_dirs_with_glob(public_dirs : Array(Hash(String, String)))
- #static_dir_entry(source_path : String, static_path : String, file_path : String) : Hash(String, String)
- #ts_controller_method_bodies_for_directory(package_controller_method_bodies : Hash(String, Hash(String, Array(Noir::GoCalleeExtractor::FunctionBody))), dir : String) : Hash(String, Array(Noir::GoCalleeExtractor::FunctionBody))
-
#ts_controller_methods_for_directory(package_controller_methods : Hash(String, Hash(String, Array(String))), dir : String) : Hash(String, Array(String))
Returns the cross-file controller-method map for the given directory, or an empty map.
-
#ts_function_bodies_for_directory(package_function_bodies : Hash(String, Hash(String, Noir::GoCalleeExtractor::FunctionBody)), dir : String) : Hash(String, Noir::GoCalleeExtractor::FunctionBody)
Returns the cross-file function-body map for the given directory, or an empty map when the directory has no captured functions.
-
#ts_groups_for_directory(package_groups : Hash(String, Hash(String, String)), dir : String) : Hash(String, String)
Returns the cross-file group map for the given directory, or an empty map when the directory has no registered groups.
Instance methods inherited from class Analyzer
analyze
analyze,
base_path : String
base_path,
base_paths : Array(String)
base_paths,
callees_needed? : Bool
callees_needed?,
logger : NoirLogger
logger,
parallel_analyze(files : Array(String), &block : String -> Nil)
parallel_analyze,
read_file_content(path : String) : String
read_file_content,
result : Array(Endpoint)
result,
url : String
url
Constructor methods inherited from class Analyzer
new(options : Hash(String, YAML::Any))
new
Macros inherited from class Analyzer
define_getter_methods(names)
define_getter_methods
Instance methods inherited from module FileHelper
all_files : Array(String)
all_files,
get_files_by_extension(extension : String) : Array(String)
get_files_by_extension,
get_files_by_prefix(prefix : String) : Array(String)
get_files_by_prefix,
get_files_by_prefix_and_extension(prefix : String, extension : String) : Array(String)
get_files_by_prefix_and_extension,
get_public_dir_files(base_path : String, folder : String) : Array(String)
get_public_dir_files,
get_public_files(base_path : String, anchors : Array(String) = ["shard.yml", "Gemfile"]) : Array(String)
get_public_files
Class Method Detail
*_test.go is Go's hard-wired build-tag for test-only source.
go build excludes these files entirely; only go test pulls
them in. Real route handlers never live there, but framework
repos (echo, chi, gin) park hundreds of e.GET("/...", ...)
calls in *_test.go to exercise the router. Skip both in the
cross-file pre-passes (so test-file groups don't pollute the
production group map) and in each analyzer's per-file loop.
Also skip Go's toolchain-ignored directory prefixes: any
path component starting with _ (_examples/, _assets/,
_testdata/) is excluded by go build/go list outright.
kataras/iris alone parks 392 phantom endpoints under
_examples/...; they're documented apps, not production
routes the framework ships.
Instance Method Detail
Builds {import_path => {function_name => body}} for local Go
packages under the configured base paths. This is gated on callee
demand and reuses package_function_bodies, so default route scans
do not pay for go.mod discovery. It lets generated routers like
Hertz resolve feed.Feed when feed imports a sibling package from
the same module.
Builds {import_path => {method_name => [body, ...]}} for local Go
packages under the configured base paths. This complements
#collect_import_path_function_bodies for route handlers referenced
as method values on imported package instances, e.g.
handler := api.NewHandler(svc); app.Get("/x", handler.Show).
Per-directory {method_name => [FunctionBody, ...]} map for
controller-style routes whose handler is referenced by method name
(Beego's web.Router("/x", &Ctrl{}, "get:Method")). Lets the
analyzer walk the controller method's body for callees even though
the registration call doesn't pass the handler as an argument.
Gated on callees_needed? so default scans pay nothing.
--- Beego controller-method pre-pass --------------------------------
Builds a per-directory {controller_type => [http_verb_methods]} map
so mapping-less web.Router("/x", &Ctrl{}) registrations resolve to
the exact methods the controller implements. Keyed by directory
because Beego controllers and their router registrations share a Go
package (== directory); a controller defined in a sibling file is
still found.
--- Cross-file function body pre-pass --------------------------------
Walks every cached .go source in file_contents and collects
top-level function_declaration nodes into a per-directory map
so cross-file identifier-handler resolution in
Noir::GoCalleeExtractor is O(1) at lookup time. The map is
keyed by directory because Go's name resolution rules are scoped
to a single package (== single directory), so we never have to
worry about cross-package leakage.
--- Tree-sitter group/route pre-pass --------------------------------
Does a cross-file fixpoint over every .go file in each package
directory, extracting group declarations (x := r.Group("/x") and
friends). Returns:
package_groups— per-directory{group_name => resolved_prefix}file_contents— cached source strings keyed by path, so the per-file second pass doesn't read files twice
group_method is the method name used for grouping — "Group" for
Gin/Echo/Fiber/Hertz (default), "Party" for Iris, "Subrouter"
for Mux.
The fixpoint handles the routes.go calling v1.GET(...) under a
v1 := r.Group("/v1") declared in main.go case — iterate until
no new entries land. In-file declarations win over external ones.
import_marker, when given, restricts the cross-file group/engine
pre-pass to files that actually import the framework. Group
variables (v1 := r.Group("/v1")) and root-engine bindings only
ever appear in framework-importing files, so skipping the rest
avoids parsing unrelated .go files — a large saving in mixed
repos (e.g. an example monorepo where most dirs use other routers).
file_contents is still populated for every file so the per-file
route pass and callee pre-pass keep their read cache.
Per-package directories that import a target framework. Some real
projects hide the concrete framework type behind a local interface, so
the file that calls router.GET(...) may not import Gin/Echo itself.
Cheap gate before the tree-sitter route pass. Handler-only files often
import Gin/Echo for *gin.Context / echo.Context, but they cannot emit
endpoints unless they contain a route/static registration call.
Read every .go file once into a {path => source} hash. Used by
analyzers (Goyave) that don't otherwise call
#collect_package_groups_ts but still need the file_contents hash
as input to #collect_package_function_bodies.
Returns the cross-file controller-method map for the given directory, or an empty map.
Returns the cross-file function-body map for the given directory, or an empty map when the directory has no captured functions.