Documentation
¶
Overview ¶
Package detect contains every lagotto layout-smell detector and the cobra subcommand factories that expose them.
Smells ¶
See README.md and docs/patterns/ for full descriptions, examples, and remediation guidance. The catalog at a glance:
- G1 — Receiver Monolith
- G1B — Decomposition Theatre
- G1C — Aggregate Holder
- G1D — Hidden Holder via Registry
- G2 — Stutter Names
- G3 — Build-Tag Pair Sprawl
- G4 — God Dependency Bag
- G5 — Mixed-Concern File
- G6 — Facade Method
- G7 — Init Coupling
- G8 — Internal Re-Export Tunnel
- G9 — Prefix Cluster
- G10 — Shadow Suffix
- G11 — Junk Drawer
- G12 — Premature Package
Output contract ¶
Every detector returns a slice of audit.Finding values. The CLI aggregates them into an audit.Report and serializes JSON (default) or text. JSON is the stable contract; downstream tooling depends on the field names.
Architecture ¶
One file per detector (receivers.go, deps.go, mixed.go, …) with each detector exposing a Scan*() entry point. Cross-detector helpers live in support.go and concerns.go. The cobra subcommand factories — AuditCmd, MonolithsCmd, StutterCmd, FacadesCmd, DepsCmd, MixedCmd, FSCmd, InitsCmd, TunnelCmd — are defined in cmd.go and wired up by cmd/lagotto/main.go.
Index ¶
- func AuditCmd(f *Flags) *cobra.Command
- func DepsCmd(f *Flags) *cobra.Command
- func FSCmd(f *Flags) *cobra.Command
- func FacadesCmd(f *Flags) *cobra.Command
- func InitsCmd(f *Flags) *cobra.Command
- func MixedCmd(f *Flags) *cobra.Command
- func MonolithsCmd(f *Flags) *cobra.Command
- func ScanDepsBag(pkgs []*packages.Package) []audit.Finding
- func ScanFS(root string, pkgs []*packages.Package, exclude []string) []audit.Finding
- func ScanFacades(pkgs []*packages.Package) []audit.Finding
- func ScanInitCoupling(pkgs []*packages.Package) []audit.Finding
- func ScanMixedConcern(pkgs []*packages.Package) []audit.Finding
- func ScanReExportTunnel(pkgs []*packages.Package) []audit.Finding
- func ScanReceivers(pkgs []*packages.Package) []audit.Finding
- func ScanStutter(pkgs []*packages.Package) []audit.Finding
- func StutterCmd(f *Flags) *cobra.Command
- func TunnelCmd(f *Flags) *cobra.Command
- type Flags
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func AuditCmd ¶
AuditCmd returns the `audit` subcommand: run every detector and emit the aggregated report.
func FacadesCmd ¶
FacadesCmd returns the `facades` subcommand: G6.
func MonolithsCmd ¶
MonolithsCmd returns the `monoliths` subcommand: G1/G1B/G1C/G1D.
func ScanDepsBag ¶
ScanDepsBag finds struct types whose name matches the dependency- bag pattern and counts heterogeneous field package types.
func ScanFS ¶
ScanFS aggregates every filesystem-level smell (G3, G9, G10, G11, G12) for each package directory under root. Filesystem detectors reason about directory listings, not AST; the loaded packages are only used to determine the directory set, with a filesystem walk fallback when no packages were loaded.
func ScanFacades ¶
ScanFacades inspects every method body to find thin pass-throughs to a function in a different package.
A method is a facade when:
- Its body has 1 statement that is a ReturnStmt or ExprStmt with a single CallExpr, and the callee resolves to a function in a different package.
- Or its body has 2-3 statements where all but the final return are trivial guards/assignments and the final statement is the above pattern.
Methods on types that embed an interface in another package are flagged with reduced severity (interface-dispatch facades may be load-bearing).
func ScanInitCoupling ¶
ScanInitCoupling flags packages that have multiple `func init()` declarations spread across more than one file. Go runs init() functions in alphabetical filename order (and source order within a file), so cross-file init coupling depends on an implicit ordering rule that is fragile when files are renamed or split.
Single-file multiple init() is not flagged: the source-order rule is local and visible.
func ScanMixedConcern ¶
ScanMixedConcern flags files that mix three or more declaration groups (types, methods, validation, utilities) over the 100-line floor. The smell predicts the file is a junk drawer disguised as a module.
func ScanReExportTunnel ¶
ScanReExportTunnel finds packages whose top-level public surface is dominated by re-exports from a single deeper package. This is the TypeScript "barrel" pattern, which is wrong in Go: it adds indirection, makes call paths harder to trace, and the package has no genuine identity of its own.
A re-export is one of:
type X = otherPkg.Y (type alias to another pkg)
var X = otherPkg.Y (variable bound to qualified ident)
func X(args) ret { return otherPkg.X(args...) } (transparent function wrapper)
A package is flagged when ≥50% of its exported top-level decls are re-exports AND a single target package accounts for at least half of those re-exports.
func ScanReceivers ¶
ScanReceivers returns Receiver Monolith (G1) findings computed from the type-checker's full method set on each named struct, plus Decomposition Theatre (G1B) findings for alias clusters that pretend to split a god type without actually moving methods.
Counting via the method set (rather than source-AST receiver names) is critical: a god type that "decomposes" itself by embedding a helper struct and adding nine type aliases (`type Mutator = helper`) is the same monolith with a costume on. The method-set view sees through both tricks because Go's type system promotes methods through embedding and resolves aliases.
func ScanStutter ¶
ScanStutter detects exported types and functions whose names start with the package name (case-insensitive at the leading segment, identifier-aware so `lanes.LaneConfig` is flagged but `lanes.Land` is not).
func StutterCmd ¶
StutterCmd returns the `stutter` subcommand: G2.