class

Analyzer::Fsharp::Giraffe

Inherits Analyzer < FileHelper < Reference < Object

Giraffe is a functional web framework on top of ASP.NET Core. Routes are HttpHandler values composed via the >=> Kleisli operator and collected with choose [...]. Common combinators surfaced here:

  • route "/path" — exact path match
  • routeCi "/path" — case-insensitive variant
  • routex "regex" — regex variant (path is reported verbatim)
  • routef "/users/%i/%s" — typed parameters
  • subRoute "/prefix" handler and friends — mount nested routes

HTTP method filters (GET, POST, etc.) appearing on the same textual line as a route are honored; lines without an explicit method default to a fallback set.

Constants

FALLBACK_METHODS = ["GET", "POST", "PUT", "DELETE", "PATCH"]
HTTP_METHODS = ["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"] of ::String
METHOD_WORD_PATTERNS = HTTP_METHODS.map do |m| {m, /\b#{m}\b/} end
NO_UTF_CHECK = Regex::MatchOptions::NO_UTF_CHECK

PCRE2 (Crystal's regex backend) re-validates UTF-8 encoding of the subject on every match_at_byte_index call by default -- an O(remaining-length) pass, since our scan loop calls it at every character position that O(n²) rather than O(n). content (and cleaned, built from it) is always sourced through Analyzer#read_file_content, which reads with invalid: :skip, so both are guaranteed structurally valid UTF-8 already -- the same invariant String#scan in the standard library relies on when it sets this same option after its first match. Confirmed empirically: a 4x-larger synthetic file went from ~16.7s to ~0.014s once this was applied to the combinator matchers below (~1000x).

ROUTE_BIND_RE = /\GrouteBind(?:\s*<[^>\n]*>)?\s+"([^"]+)"/
ROUTE_COMBINATOR = /(?:route(?:Bind|Ci[fx]?|xp?|f)?|subRoute(?:Ci|f)?)\b/

Crystal recompiles an interpolated regex literal on every evaluation (a full PCRE2 JIT compile). Both the stop-line matcher and the per-verb window probes interpolate only fixed patterns, so precompile them once at load time.

ROUTE_CONST_RE = /\G(?:routeCix|routexp|routeCi|routex|route)\s+([A-Za-z_][A-Za-z0-9_']*(?:\.[A-Za-z_][A-Za-z0-9_']*)*)/
ROUTE_HANDLER_STOP_RE = /\A(?:(?:GET|POST|PUT|DELETE|PATCH|HEAD|OPTIONS)\b.*\b#{ROUTE_COMBINATOR}|#{ROUTE_COMBINATOR})/
ROUTE_RE = /\G(?:routeCix|routexp|routeCi|routex|route)\s+"([^"]+)"/
ROUTEF_PARAM_TYPES = {'i' => "int", 'd' => "int64", 'b' => "bool", 'c' => "char", 's' => "string", 'f' => "float", 'O' => "guid", 'u' => "uint64"}

Mapping of routef format specifiers to noir path-param types.

ROUTEF_RE = /\G(?:routef|routeCif)\s+"([^"]+)"/
SUB_ROUTE_RE = /\G(subRoute(?:Ci|f)?)\s+"([^"]+)"\s*([\(\[])/

Combinator matchers for the main scan loop below. \G (rather than \A) anchors each match to the exact byte offset passed to Regex#match_at_byte_index, mirroring what \A did against a freshly sliced cleaned[i..] remainder -- but without the slice.

VERB_CHOOSE_RE = /\G(GET_HEAD|GET|POST|PUT|DELETE|PATCH|HEAD|OPTIONS)\s*>=>\s*choose\s*\[/

GET_HEAD is Giraffe's own Endpoint-Routing combinator for [ GET; HEAD ]; it must come first in the alternation so GET cannot claim its prefix. VERB_METHODS maps a matched token to the verbs it actually applies.

VERB_LIST_RE = /\G(GET_HEAD|GET|POST|PUT|DELETE|PATCH|HEAD|OPTIONS)\s*\[/
VERB_METHODS = {"GET_HEAD" => ["GET", "HEAD"]}

Verbs a matched Endpoint-Routing verb token dispatches on. Only tokens that mean more than themselves need an entry.

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