Documentation
¶
Overview ¶
Package analyzers holds every detector behind `gofastr verify`.
The rules themselves, IDs, severities, the Why and the Fix, live in github.com/DonaldMurillo/gofastr/framework/contracts. This package only finds the code. That split is deliberate: the catalog has to be readable and serveable (over MCP, in docs) without dragging in a Go parser, and an analyzer has to be replaceable without touching the documentation contract it satisfies.
Analyzers here are AST-based rather than type-checked. The trade is explicit: a type-checked pass would be more precise and would need a full `go/packages` load of the module, which costs seconds and fails outright on a project that does not compile. Verify has to be useful mid-edit, so precision is bought back with narrow patterns and suppression rather than with types.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func AuthWiring ¶
AuthWiring reports whether the module configures auth and whether anything reads it.
Types ¶
type EntityDecl ¶
EntityDecl is one `app.Entity(...)` / `GroupEntity(...)` call.
type EntityInfo ¶
type EntityInfo struct {
Name string
Fields []string
// FieldsResolved is false when Fields came from a helper call rather
// than a literal slice. The scoping rules stay quiet in that case:
// they cannot see the columns, and guessing would mean either false
// findings or a false all-clear.
FieldsResolved bool
CRUDDisabled bool
MCP bool
Public bool
HasAccess bool
OwnerField string
MultiTenant bool
// AccessPermissions are the permission strings the entity's Access
// block names. These are the permissions least likely to be exercised
// by accident: nothing in the app calls them by name, so only a real
// request through the CRUD layer can prove them.
AccessPermissions []string
File string
Line int
Pos token.Pos
}
EntityInfo is what the static pass can recover from an entity registration. It is a subset of framework/entity.EntityConfig, only the fields that decide exposure and scoping, read straight off the composite literal.
func Entities ¶
func Entities(p *contracts.Pass) []EntityInfo
Entities returns every statically readable entity registration.
func (EntityInfo) Exposed ¶
func (e EntityInfo) Exposed() bool
Exposed reports whether the entity has a generated surface at all. CRUD defaults to on, so only an explicit false turns it off.
func (EntityInfo) Scoped ¶
func (e EntityInfo) Scoped() bool
Scoped reports whether the entity limits which rows a caller can reach.
type EventSub ¶
type EventSub struct {
// Type is the event type string the handler listens for.
Type string
File string
Line int
Pos token.Pos
}
EventSub is one statically discovered event subscription.
type HookDecl ¶
type HookDecl struct {
// Entity is the entity name the hook is attached to.
Entity string
// Type is the lifecycle point, lower-cased to match the manifest
// ("beforecreate", "afterupdate", …).
Type string
File string
Line int
Pos token.Pos
}
HookDecl is one statically discovered lifecycle-hook registration.
type RoleGrant ¶
type RoleGrant struct {
// Role is the role name granted permissions.
Role string
File string
Line int
Pos token.Pos
}
RoleGrant is one statically discovered role definition.
type Route ¶
type Route struct {
// Method is the HTTP verb exactly as written, case included, since a
// lowercase one is a finding rather than something to normalise away.
Method string
// Pattern is the full path with any resolvable group prefix applied.
Pattern string
// RawPattern is the literal passed at the call site, before prefixing.
RawPattern string
// Group is the receiver identifier, "" for a direct router call.
Group string
// Guarded is true when the route was registered on a group carrying
// access or middleware, which is the framework's guarding seam.
Guarded bool
// Handler is the handler expression, for evidence.
Handler string
// Screen marks a route declared through `app.NewScreen`. Screens are
// matched by core-ui's own router, NOT by ServeMux, and that router
// takes `:id` parameters natively. It even rewrites `{id}` into
// `:id`. Every rule about ServeMux pattern syntax must therefore skip
// them, or it reports the correct spelling as a bug.
Screen bool
// Package is the import path of the registering package. Duplicate
// detection is scoped by it: two example apps in one repository both
// serving "/healthz" are not a conflict, they are two programs.
Package string
File string
Line int
Col int
Pos token.Pos
}
Route is one statically discovered registration.
type RouteTable ¶
type RouteTable struct {
Routes []Route
Entities []EntityDecl
// Registered is true when at least one registration was found,
// distinguishing "no routes" from "this project does not register
// routes in a way the static pass can see". Analyzers stay quiet in
// the second case rather than reporting an empty app.
Registered bool
}
RouteTable is everything the static pass could learn about the app's surface. It is memoized on the pass, so the routing, permissions, testing, and guidance analyzers all read one traversal.
func Routes ¶
func Routes(p *contracts.Pass) *RouteTable
Routes returns the pass's route table, computing it at most once.
type SheetInput ¶ added in v0.86.0
SheetInput is one owned-style sheet the shared program checks read: its pass-relative path and its CSS bytes.
type StyleGroup ¶ added in v0.86.0
type StyleGroup struct {
// GOOS and GOARCH are the platform the closure was computed for.
GOOS, GOARCH string
// MainDir is the pass-relative directory of the package main; ""
// for the unreached group.
MainDir string
// Dirs are the pass-relative, slash-separated directories of the
// program's import closure, sorted; empty for the unreached group.
Dirs []string
// Sheets and TokensFiles are the pass-relative sheet and tokens
// file paths under Dirs, sorted.
Sheets, TokensFiles []string
// Tokens is the token map this group's sheets are judged against.
Tokens map[string]string
// AppTokens is every app token that parsed, in file order.
AppTokens []ownstyle.AppTokenAt
// ParsedTokens holds each tokens file's parse, keyed by path; a
// file two programs reach parses identically in both.
ParsedTokens map[string]*ownstyle.TokensFile
// TokenFindings are this group's tokens-file checks (the call
// `gofastr gen styles` makes), in check order.
TokenFindings []ownstyle.FileDiagnostic
}
StyleGroup is one program's share of the owned-style universe: the sheets and tokens files whose directories the program's import closure contains, plus (as the final group) what no program reaches — library packages meant to be composed into one app, still checked against each other. Each group carries the target platform its closure was computed for (build constraints are honoured, so one main with platform-specific imports can yield several groups) and the token map that program's sheets are judged against: the built-in theme plus that group's app tokens. Groups come in deterministic order — by main directory, then platform, the unreached group last — and their members are sorted by path.
func OwnedStyleGroups ¶ added in v0.86.0
func OwnedStyleGroups(p *contracts.Pass, sheets, tokensFiles []SheetInput) []StyleGroup
OwnedStyleGroups groups the given owned sheets and tokens files (pass-relative paths) by program, checks each group's tokens files together (the call `gofastr gen styles` makes) and fills each group's token map, and appends one unreached group for what no program reaches. A pass with no buildable main package leaves every sheet in the unreached group — the whole-tree behaviour for library-only repos.
type StyleProgramChecks ¶ added in v0.86.0
type StyleProgramChecks struct {
Groups []StyleGroup
// SheetFindings maps each input sheet path to its ownstyle.Check
// findings across every group that reaches it — a binary only
// carries its own tokens, so a sheet two programs share must
// satisfy each — with identical findings collapsed to one, sorted
// by line, column, rule, message.
SheetFindings map[string][]ownstyle.Diagnostic
// DuplicateNames maps each sheet whose owner name another sheet of
// one program shares to the sorted other sheets of every such
// program (GOFASTR1816's shape).
DuplicateNames map[string][]string
// RepeatedLiterals are the GOFASTR1822 occurrences, one per site
// with every program's partners merged into the message.
RepeatedLiterals []ownstyle.FileDiagnostic
}
StyleProgramChecks is the per-program owned-style judgement both `gofastr verify` and `gofastr gen styles` run: the groups, each sheet's findings judged against every group that reaches it, the duplicate owner names, and the repeated literals.
func CheckStylePrograms ¶ added in v0.86.0
func CheckStylePrograms(p *contracts.Pass, sheets, tokensFiles []SheetInput) StyleProgramChecks
CheckStylePrograms runs the shared per-program owned-style checks: the grouping (see OwnedStyleGroups), each sheet's ownstyle.Check findings against every group that reaches it, the duplicate owner names, and the repeated literals. tokensFiles carries the app tokens files the same way. `gofastr verify` renders these as diagnostics; `gofastr gen styles` prints them and lets them decide what generates. One implementation: the two cannot disagree.