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
- G1E — Foreign Holder
- G2 — Stutter Names
- G3 — Build-Tag Pair Sprawl
- G4 — God Dependency Bag
- G5 — Disconnected File Concerns
- G6 — Facade Method
- G7 — Init Coupling
- G8 — Internal Re-Export Tunnel
- G9 — Prefix Cluster
- G10 — Shadow Suffix
- G11 — Generic Filename
- G12 — Premature Package
- G13 — Large Cohesive File
- G14 — Cross-Layer Orchestration
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, LayersCmd — 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 LayersCmd(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 ScanLayerPolicy(pkgs []*packages.Package, rules []LayerPolicyRule) []audit.Finding
- func ScanMixedConcern(pkgs []*packages.Package) []audit.Finding
- func ScanMixedConcernWithOptions(pkgs []*packages.Package, options MixedOptions) []audit.Finding
- func ScanReExportTunnel(pkgs []*packages.Package) []audit.Finding
- func ScanReceivers(pkgs []*packages.Package) []audit.Finding
- func ScanRoot(args []string) string
- func ScanStutter(pkgs []*packages.Package) []audit.Finding
- func StutterCmd(f *Flags) *cobra.Command
- func TunnelCmd(f *Flags) *cobra.Command
- func ValidateLayerPolicyRules(rules []LayerPolicyRule) error
- func ValidateMixedOptions(options MixedOptions) error
- type Flags
- type LayerPolicyRule
- type MixedOptions
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 LayersCmd ¶ added in v0.2.4
LayersCmd returns the `layers` subcommand: configured G14 policies.
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. It walks the filesystem directly because a loaded package only exposes files selected for the current build tags. Loaded package metadata is used only to map directories to import paths for G12 production-reuse evidence.
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 files when an init in one file reads package-level state written by an init in another. This establishes a real cross-file ordering dependency rather than merely counting independent registration inits.
Single-file multiple init() is not flagged: source order is local and visible.
func ScanLayerPolicy ¶ added in v0.2.4
func ScanLayerPolicy(pkgs []*packages.Package, rules []LayerPolicyRule) []audit.Finding
ScanLayerPolicy reports configured cross-layer orchestration. It is opt-in: no rules means no findings. The detector uses typed call targets so aliases and local import names do not affect its result.
func ScanMixedConcern ¶
ScanMixedConcern flags very large files only when their top-level declarations form at least two substantial disconnected reference clusters. The graph includes implicit interface-implementation edges so idiomatic Go interface families remain one cohesive component.
func ScanMixedConcernWithOptions ¶ added in v0.2.4
func ScanMixedConcernWithOptions(pkgs []*packages.Package, options MixedOptions) []audit.Finding
ScanMixedConcernWithOptions runs G5 with explicit thresholds and severity.
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 ScanRoot ¶ added in v0.2.4
ScanRoot exposes the normalized target root for CLI configuration loading.
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.
func ValidateLayerPolicyRules ¶ added in v0.2.4
func ValidateLayerPolicyRules(rules []LayerPolicyRule) error
ValidateLayerPolicyRules rejects incomplete policy and malformed severity before package loading begins.
func ValidateMixedOptions ¶ added in v0.2.4
func ValidateMixedOptions(options MixedOptions) error
ValidateMixedOptions rejects non-positive thresholds and unknown severities.
Types ¶
type Flags ¶
type Flags struct {
Tags string
Format string
Exclude []string
Suppress []string
FailOn string
ConfigPath string
LoadedConfigPath string
Mixed MixedOptions
MixedSeverity string
LayerPolicy []LayerPolicyRule
}
Flags carries the persistent CLI flag values shared by every subcommand. cmd/lagotto/main.go binds these to cobra persistent flags; the detect package reads them at RunE time.
type LayerPolicyRule ¶ added in v0.2.4
type LayerPolicyRule struct {
Name string
Paths []string
Dependencies []string
GeneratedTypes []string
MaxCoordinatedDependencies int
Severity audit.Severity
}
LayerPolicyRule is one resolved, repository-owned G14 policy. Patterns may be full import paths or module-relative globs using *, **, and ?.
type MixedOptions ¶ added in v0.2.4
type MixedOptions struct {
MinLines int
MinComponentMembers int
MinComponentLines int
MinSingleComponentComplexity int
Severity audit.Severity
CohesiveMinLines int
}
MixedOptions controls G5's evidence floor and severity plus G13's separate cohesive-file navigation threshold. Defaults favor precision.
func DefaultMixedOptions ¶ added in v0.2.4
func DefaultMixedOptions() MixedOptions
DefaultMixedOptions returns Lagotto's precision-oriented G5 policy.