class

Analyzer::Go::Huma

Inherits Analyzer::Go::GoEngine < Analyzer::Go::GoTestPath < Analyzer < FileHelper < Reference < Object

Huma (https://huma.rocks/) is an OpenAPI-first Go framework where every operation is registered through huma.Register(api, huma.Operation{Method: ..., Path: ...}, handler) The Operation literal carries method/path verbatim, and the handler's Input struct fields declare parameter shape via tags (path:"id", query:"limit", header:"X-Auth", plus a Body field for request bodies). That makes extraction unusually precise compared to other Go routers.

Constants

DEFAULT_SECURITY = /(?:\b(\w+)\s*\.\s*OpenAPI\s*(?:\(\s*\))?|\b(\w+))\s*\.\s*Security\s*=\s*(\[\]map\[string\]\[\]string\s*\{(?:[^{}]|\{(?:[^{}]|\{[^{}]*\})*\})*\}|[A-Za-z_]\w*)/

The API's default security, set on its OpenAPI document: cfg.OpenAPI.Security = …, api.OpenAPI().Security = …, or oapi.Security = … with oapi := api.OpenAPI(). Not op.Security = … in an operation or group modifier, which sets one operation's.

HANDLER_FUNC = /^func\s+(\w+)\s*\(\s*\w+\s+context\.Context\s*,\s*\w+\s+\*?(?:\w+\.)?(\w+)/m

func labelsList(ctx context.Context, in *labelsListInput) (…); the input is struct for an inline in *struct {…}.

HTTP_METHOD_CONSTANTS = {"http.MethodGet" => "GET", "http.MethodPost" => "POST", "http.MethodPut" => "PUT", "http.MethodPatch" => "PATCH", "http.MethodDelete" => "DELETE", "http.MethodHead" => "HEAD", "http.MethodOptions" => "OPTIONS", "http.MethodConnect" => "CONNECT", "http.MethodTrace" => "TRACE", "http.MethodQuery" => "QUERY"}
IMPORT_MARKER = "github.com/danielgtaylor/huma"
IMPORT_MARKER_RE = Regex.union(IMPORT_MARKER)

One precompiled matcher instead of a String#includes? scan per .go file: includes? runs Rabin-Karp over the whole buffer and the marker is absent in the overwhelming majority of files in a polyglot repo, so every one of them pays the full scan. See Analyzer#content_matches?.

MODIFIER_PARAM = /\Afunc\s*\(\s*(\w+)\s+\*\s*huma\.Operation\b/

p.Security = … inside a modifier taking p *huma.Operation.

NO_AUTOPATCH = /"autopatch"\s*:\s*false/

autopatch disabled for an operation by its metadata.

OPENAPI_VAR = /\b(\w+)\s*:?=\s*[\w.]+\s*\.\s*OpenAPI\b(?:\s*\(\s*\))?/
OPERATION_FUNC = /^func\s+(\w+)\s*(?:\[[^\]\n]*\])?\s*\(([^)]*\bhuma\.Operation\b[^)]*)\)/m

A function taking a huma.Operation parameter, for wrapper detection.

PARAM_TAG_KINDS = {"path" => "path", "query" => "query", "header" => "header", "cookie" => "cookie"}

Tags we lift from Input struct fields onto endpoint params.

PARAM_TAG_PATTERNS = PARAM_TAG_KINDS.map do |go_tag, param_type| {param_type, /#{go_tag}:"([^"]+)"/} end

Crystal recompiles an interpolated regex literal on every evaluation (a full PCRE2 JIT compile) — precompile the fixed tag matchers once at load time instead of per struct field.

SCALAR_BODY_TYPES = {"string", "bool", "int", "int64", "int32", "float64", "any", "interface{}"}
SECURITY_LITERAL = /\[\]map\[string\]\[\]string\s*\{(?:[^{}]|\{(?:[^{}]|\{[^{}]*\})*\})*\}/

[]map[string][]string{{"JWTKeyAuth": {}}, {"APITokenAuth": {}}}: an OpenAPI security requirement list, three brace levels deep at most.

SECURITY_VAR = /(?<![.\w])(\w+)\s*=\s*(\[\]map\[string\]\[\]string\s*\{(?:[^{}]|\{(?:[^{}]|\{[^{}]*\})*\})*\})/
SERVER_URL = /huma\.Server\s*\{\s*\{?\s*URL\s*:\s*(?:"([^"]*)"|(\w+))\s*[,}]/
SERVERS_ASSIGN = /\.\s*Servers\s*=\s*([^\n]+)/

The servers of the API's document: cfg.Servers = … / oapi.Servers = …, a literal or a variable holding one.

SUGAR_VERBS = {"huma.Get" => "GET", "huma.Post" => "POST", "huma.Put" => "PUT", "huma.Patch" => "PATCH", "huma.Delete" => "DELETE", "huma.Head" => "HEAD", "huma.Options" => "OPTIONS"}

Huma v2's typed convenience helpers — huma.Get(api, "/path", handler) and friends — register an operation without the verbose huma.Register(api, huma.Operation{...}, handler) literal. The verb is the method name; the path is the SECOND argument (the first is the API/group). Mapped here so the call walker can decode them alongside huma.Register.

Class methods

tech_name
Source

Instance methods

analyze
Source
tech

Instance-side view of the same declaration. The per-file rescues live on this base class, which has no way to name the analyzer that is running inside them, so a skipped file could not be attributed to a tech. Deriving it from analyzer_for keeps the name written exactly once.

Source

Nested types