Analyzer::Zig::Cli
Inherits CliEndpointSupport < Analyzer < FileHelper < Reference < Object
Surfaces the command-line attack surface of Zig programs as cli://
endpoints: zig-clap param strings, zig-cli literals, zig-args struct
fields, yazap App/Arg builder calls, plus std.process argv / env reads.
Line-scan, merged by URL.
Constants
builtin.
zig-args: argsParser.parseForCurrentProcess(Options, allocator, .print)
/ argsParser.parse(Options, &iterator, allocator, .print). The
receiver MUST be the local alias bound to @import("args") (captured
via ARGS_IMPORT_ALIAS_RE below) -- otherwise an unrelated .parse(...)
call on some other receiver (e.g. a URI parser also exposing a parse
method) could be mistaken for the CLI's option struct. The type name is
resolved to its const <Name> = struct { ... }; declaration (or, for
an inline anonymous struct literal, the call site itself) and every
top-level field becomes a flag.
zig-clap multiline param string lines (each begins with \\).
zig-cli struct literals. (Only flags are extracted: a .name literal is
ambiguous between the app name, a subcommand, and a positional-arg name,
so subcommand extraction from zig-cli is a follow-up.)
The subset of MARKERS that is either library-specific API usage or a
bare import that pre-dates this file's zig-args/yazap support (kept
as-is: an established, non-regressed convention elsewhere in this
analyzer). A file matching only via a bare @import("args") or
@import("yazap") -- with no corresponding API call anywhere in the
file -- is NOT proof of a CLI surface (a project can vendor an
unrelated module that happens to be named "args"), so it must not
seed a zero-evidence cli://<binary> root endpoint.
yazap doesn't need a separate evidence constant here: its bare
@import("yazap") alone never seeds an endpoint either, because
YAZAP_ROOT_RE / YAZAP_SUBCMD_RE / YAZAP_ADD_ARG_RE (used later, in the
same forward pass) only call fetch_endpoint when they find a genuine
rootCommand/createCommand/addArg call -- so an import with no real
yazap usage naturally yields zero endpoints once the root pre-seed
below is gated on STRONG_MARKERS.
yazap: App.init(...), app.rootCommand(), app.createCommand("name", ...)
and <receiver>.addArg(Arg.positional/booleanOption/singleValueOption(...)).
Receiver variables are mapped to their command URL incrementally, in
the SAME forward pass as the addArg scan (see analyze below), so a
variable reused across subcommands (e.g. a generic cmd) resolves to
whichever command was assigned to it as of that line, never a
whole-file map where a later reassignment retroactively overwrites an
earlier addArg's receiver.
Class methods
Instance methods
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.