class

Analyzer::CSharp::FastEndpoints

Inherits Analyzer::CSharp::Common < Analyzer < FileHelper < Reference < Object

Constants

AUTO_ACCESSORS_RE = /\A\{\s*get\s*;/

A public auto-property's accessor list ({ get; set; }).

BASE_TYPE_REGEX = /:\s*(?:[A-Za-z_][A-Za-z0-9_]*\s*,\s*)*(Endpoint(?:WithoutRequest)?(?:<[^>]*>)?|Ep<[^>]*>)/

Endpoint<TRequest>, Endpoint<TRequest, TResponse>, EndpointWithoutRequest, EndpointWithoutRequest<TResponse>, and the Ep short alias all subclass the FastEndpoints endpoint primitive. Any class matching one of these as a base is a candidate.

ENDPOINT_SOURCE_RE = /\bFastEndpoints\b|:\s*(?:[A-Za-z_][\w.]*\s*,\s*)*(?:Endpoint(?:WithoutRequest)?\b|Ep\s*<)/

Whole-file gate. One JIT-compiled union beats the two String#includes? scans it replaces, and it also refuses files that merely mention the word "Endpoint" without declaring a FastEndpoints class.

FROM_ATTRIBUTES = {"FromQuery" => "query", "FromRoute" => "path", "FromBody" => "json", "FromHeader" => "header", "FromForm" => "form", "FromCookie" => "cookie", "FromClaim" => "service", "BindFrom" => "", "QueryParam" => "query", "RouteParam" => "path", "FromKeyedServices" => "service", "FromServices" => "service"}

How a request DTO's property attribute binds it ("": by the verb's default); service is never request input.

GROUP_CALL_REGEX = /\bGroup\s*<\s*(?:[\w.]+\.)?(\w+)\s*>\s*\(\s*\)/
GROUP_CLASS_REGEX = /\bclass\s+(\w+)\s*:\s*(?:Group\b|SubGroup\s*<\s*(?:[\w.]+\.)?(\w+)\s*>)/

sealed class Admin : Group { public Admin() { Configure("admin", ...); } } and the nested class Sub : SubGroup<Admin>.

GROUP_PREFIX_REGEX = /\bConfigure\s*\(\s*@?"([^"]*)"/
HTTP_VERB_TOKEN_REGEX = /(?:Http\.)?(GET|POST|PUT|PATCH|DELETE|OPTIONS|HEAD)/
PREFIX_OVERRIDE_REGEX = /\bRoutePrefixOverride\s*\(\s*@?"([^"]*)"/
ROUTE_PREFIX_REGEX = /\.\s*Endpoints\s*\.\s*RoutePrefix\s*=\s*@?"([^"]*)"/

app.UseFastEndpoints(c => c.Endpoints.RoutePrefix = "api").

ROUTES_CALL_REGEX = /\bRoutes\s*\(\s*([^)]*)\)/m
VERB_CALL_REGEX = /\b(Get|Post|Put|Patch|Delete|Options|Head)\s*\(\s*("[^)]*)\)/m

Post("/a", "/b") registers every literal, not just the first.

VERBS_CALL_REGEX = /\bVerbs\s*\(\s*([^)]*)\)/m

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