Analyzer::Crystal::Kemal
Inherits Analyzer::Crystal::CrystalEngine < FileScanEngine < Analyzer < FileHelper < Reference < Object
Constants
Any other plain name = …, which unbinds a router name reassigned to
something else (router = HTTP::Client.new in a later method). ||=
keeps an existing binding, so it is not one.
Compile-time macro var assignment, e.g. {{namespace = Routes::API::V1}}.
invidious sets it once, then registers 50+ routes as
get "/…", {{namespace}}::Videos, :videos — substituting it back lets
those routes resolve their controller and carry callees.
A def/macro line or a lambda literal: its name = … are parameter
defaults, not assignments.
Kemal's query route DSL (RFC 10008, kemalcr/kemal#769) is
Kemal-specific, unlike get/post/etc. which the shared engine's
SIMPLE_ROUTE_RE already covers for every Crystal analyzer (Amber,
Lucky). It's stitched in via match_crystal_simple_route(..., extra:)
instead of touching that shared pattern, mirroring Lucky's TRACE
extra route. The same (?:^|[^.\w]) lead-in that keeps before_get
/ after_get from matching get also keeps before_query /
after_query filters from matching here — they must not emit
endpoints.
A Kemal route hands its path a handler: a block (do |env|, { … },
&handler) or a controller action (Routes::Misc, :home, also via
{{ namespace }}). spec-kemal's client helpers share the verb names
but take none: get("/items/7"), post "/x", headers: h, body: b.
api.mount "/users", users / api.mount users: group 1 = parent,
2 = path, 3 = child. The bare DSL mount is MOUNT_PATTERN.
router = Kemal::Router.new / typed : Kemal::Router = Kemal::Router.new("/pre")
/ @@router ||= Kemal::Router.new: group 1 = name, 2 = the router's
own prefix. These names are the only receivers whose router.get "/x"
is a route: client.get "/x" on an HTTP::Client (or a spec helper)
has the same shape.
router.get "/x": group 1 = receiver, 2 = verb, 3 = path. The receiver
is checked against the file's Kemal::Router names by the caller.
serve_static false / serve_static(false) — checked on every source
line, so the two fixed OR-ed String#includes? substring scans are
precompiled into a single regex union (one PCRE2 JIT scan per line
instead of two naive substring scans).
Class methods
Instance methods
router.get "/x" where router is one of routers, trying every
x.verb "..." on the line. Returns the endpoint (empty when nothing
matches) and the receiver. Kemal registers sse as a GET route.
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.