analyzer

package
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 23, 2026 License: MIT Imports: 28 Imported by: 0

Documentation

Overview

Package analyzer implements deterministic heuristic checks for the SOLID design principles. Syntax checks always work on the Go AST; the SRP checker additionally uses standard-library go/types facts when a package resolves.

Index

Constants

This section is empty.

Variables

Rules that can individually be enabled/disabled from the CLI.

Functions

func ApplySeverity

func ApplySeverity(issues []Issue, overrides map[string]Severity)

func ApplyThresholds

func ApplyThresholds(cfg *Config, thresholds map[string]int) error

ApplyThresholds validates and applies canonical threshold keys.

func ApplyWorkspaceFilePolicy

func ApplyWorkspaceFilePolicy(pkgs []*packageFiles, patterns []string) []*packageFiles

ApplyWorkspaceFilePolicy removes generated and configured-excluded files in one mutation, then recomputes dependency facts and typed snapshots once.

func AttachDefaultSuppressions

func AttachDefaultSuppressions(issues []Issue)

AttachDefaultSuppressions adds an ignore-template fix when none are present.

func CheckDoc

func CheckDoc(id CheckID) string

CheckDoc returns a short description for a check ID when known.

func CheckHelpURI

func CheckHelpURI(id CheckID) string

CheckHelpURI returns documentation URL for a check ID when known.

func EncodeIssuesJSON

func EncodeIssuesJSON(issues []Issue) ([]byte, error)

EncodeIssuesJSON serializes findings in the canonical schema version 3 JSON format.

func Excluded

func Excluded(path string, patterns []string) bool

func FileURI

func FileURI(path string) string

FileURI returns a file:// URI for an absolute filesystem path.

func FilterExcludedFiles

func FilterExcludedFiles(pkgs []*packageFiles, patterns []string) []*packageFiles

FilterExcludedFiles applies configured excludes before any package or program-level check computes metrics, correlations, or related locations.

func FinalizeIssues

func FinalizeIssues(issues []Issue, packagePath string) error

FinalizeIssues supplies the required stable identity contract and rejects collisions before findings can reach a baseline or renderer.

func FindConfig

func FindConfig(start string) string

func FindConfigForTargets

func FindConfigForTargets(targets []string) (string, error)

FindConfigForTargets discovers configuration relative to the paths being scanned. A single run cannot safely combine different project policies, so mixed configured/unconfigured roots or multiple config files require an explicit -config selection.

func InsideAnalysisRoot

func InsideAnalysisRoot(root, filename string) bool

InsideAnalysisRoot reports whether filename lies under root.

func IsExternalPath

func IsExternalPath(root, filename string) bool

IsExternalPath reports whether filename is outside root.

func IsKnownCheckID

func IsKnownCheckID(id string) bool

IsKnownCheckID reports whether id is a registered concrete check.

func IsKnownSeverityTarget

func IsKnownSeverityTarget(key string) bool

IsKnownSeverityTarget reports whether key is a valid severity override target.

func Load deprecated

func Load(root string, includeTests bool) ([]*packageFiles, error)

Load walks root recursively, parses every non-test, non-vendor .go file, and groups them by directory (== package, for our purposes).

Deprecated: use LoadWorkspace.

func LoadWithTypes deprecated

func LoadWithTypes(root string, includeTests, withTypes bool) ([]*packageFiles, error)

LoadWithTypes optionally enriches parsed packages with standard-library go/types information. A type-check failure leaves syntax analysis usable.

Deprecated: use LoadWorkspace.

func LoadWorkspace

func LoadWorkspace(paths []string, includeTests bool, mode string) ([]*packageFiles, []string, error)

LoadWorkspace loads the requested package universe once. Keeping one go/packages load is important: go/types identities are only comparable when they come from the same load graph, which is required by module-wide OCP correlation.

mode is syntax, auto, or types. Syntax mode deliberately avoids type checking. Auto retains syntax findings when a package is ill-typed, while types returns an error for an incomplete target package.

func PortablePath

func PortablePath(root, filename string) string

PortablePath is the machine-facing path policy used by JSON, SARIF, and finding fingerprints. Repository files are returned root-relative; files outside the root are returned as normalized absolute paths.

func PortablePathForIssue

func PortablePathForIssue(issue Issue, filename string) string

PortablePathForIssue applies a finding's canonical root to a related file.

func PortableURI

func PortableURI(root, filename string) string

PortableURI converts a repository-relative path to a URI-compatible path. External files are emitted as file URIs so SARIF consumers do not mistake them for repository artifacts.

func PortableURIForIssue

func PortableURIForIssue(issue Issue, filename string) string

PortableURIForIssue applies a finding's canonical root to a related file.

func ResolveCheckSelection

func ResolveCheckSelection(profile Profile, enabledRules map[Rule]bool, enabledChecks, disabledChecks []CheckID) (map[CheckID]bool, error)

ResolveCheckSelection applies the public profile/check/family precedence in one deterministic place. Explicit enables add checks to the profile before family and disabled-check filters are applied.

func SortedSymbols

func SortedSymbols(symbols []string) []string

func ValidateConfig

func ValidateConfig(cfg Config) error

ValidateConfig applies semantic validation shared by YAML and CLI values. Keeping this separate from parsing ensures a negative or impossible CLI threshold cannot bypass the stricter file configuration path.

func ValidateExcludePatterns

func ValidateExcludePatterns(patterns []string) error

ValidateExcludePatterns rejects malformed glob segments instead of treating them as silent non-matches at runtime.

func ValidateSuppressions

func ValidateSuppressions(pkgs []*packageFiles) error

ValidateSuppressions rejects broad or unexplained suppression directives before analysis output is produced.

Types

type Check

type Check struct {
	ID          CheckID
	Name        string
	Rule        Rule
	Doc         string
	HelpURI     string
	Scope       Scope
	Maturity    Maturity
	Syntax      SyntaxSupport
	Surfaces    Surface
	HasSafeFix  bool
	DefaultSev  Severity
	RunnerGroup string
	RunPackage  func(pkg *packageFiles, cfg Config) []Issue
	RunProgram  func(pkgs []*packageFiles, cfg Config) []Issue
}

Check describes one registered analyzer runner and its metadata.

func CheckMetadata

func CheckMetadata(id CheckID) (Check, bool)

CheckMetadata returns the authoritative public metadata for a concrete check.

type CheckID

type CheckID string

CheckID identifies the concrete check that produced a finding.

const (
	CheckSRPGodType             CheckID = "SOLID-S/god-type"
	CheckSRPLowCohesionType     CheckID = "SOLID-S/low-cohesion-type"
	CheckSRPLargeType           CheckID = "SOLID-S/large-type"
	CheckSRPHighFanOutType      CheckID = "SOLID-S/high-fan-out-type"
	CheckSRPComplexFunction     CheckID = "SOLID-S/complex-function"
	CheckSRPMixedInputSurface   CheckID = "SOLID-S/mixed-input-surface"
	CheckSRPDataClump           CheckID = "SOLID-S/data-clump"
	CheckSRPFlagArgument        CheckID = "SOLID-S/flag-argument"
	CheckSRPMixedImportClusters CheckID = "SOLID-S/mixed-import-clusters"

	CheckISPFatInterface       CheckID = "SOLID-I/fat-interface"
	CheckISPUsageRatio         CheckID = "SOLID-I/usage-ratio"
	CheckISPStubImplementation CheckID = "SOLID-I/stub-implementation"

	CheckOCPTypeDispatch            CheckID = "SOLID-O/type-dispatch"
	CheckOCPDiscriminatorDispatch   CheckID = "SOLID-O/discriminator-dispatch"
	CheckOCPRuntimeExhaustiveness   CheckID = "SOLID-O/runtime-exhaustiveness"
	CheckOCPConcreteParameter       CheckID = "SOLID-O/concrete-parameter"
	CheckOCPClosedFactory           CheckID = "SOLID-O/closed-factory"
	CheckOCPImplementationCoupling  CheckID = "SOLID-O/implementation-coupling"
	CheckOCPParallelImplementations CheckID = "SOLID-O/parallel-implementations"

	CheckLSPNonExactEOF          CheckID = "SOLID-L/non-exact-eof"
	CheckLSPNilEmbeddedInterface CheckID = "SOLID-L/nil-embedded-interface"

	CheckDIPConcreteDependency CheckID = "SOLID-D/concrete-dependency"
	CheckDIPLayerImport        CheckID = "SOLID-D/layer-import"
	CheckDIPWiringOutsideRoot  CheckID = "SOLID-D/wiring-outside-root"
	CheckDIPHiddenConstruction CheckID = "SOLID-D/hidden-construction"
	CheckDIPInfraErrorLeak     CheckID = "SOLID-D/infra-error-leak"
	CheckDIPTransportLeak      CheckID = "SOLID-D/transport-leak"
)

func RegisteredCheckIDs

func RegisteredCheckIDs() []CheckID

RegisteredCheckIDs returns every concrete check ID in deterministic order.

func SelectedCheckIDs

func SelectedCheckIDs(selection map[CheckID]bool) []CheckID

SelectedCheckIDs returns selected IDs in registry order.

type Config

type Config struct {
	// Execution context used by cache and input-policy infrastructure.
	CacheDir         string
	CacheEnabled     bool
	CacheDiagnostics bool
	AnalysisMode     string
	IncludeTests     bool
	ToolVersion      string
	Profile          Profile
	EnabledChecks    []CheckID

	// SRP
	MaxMethodsPerType       int // flag types (struct) that own more methods than this
	MaxFuncLines            int // flag functions/methods longer than this many lines
	MaxFuncParams           int // examine longer parameter lists for mixed types or repeated data clumps
	MaxFieldsPerType        int
	MaxTypeLines            int
	MaxExportedMethods      int
	MaxFuncComplexity       int
	MaxTypeComplexity       int
	MaxFanOut               int
	MaxATFD                 int
	MinLargeTypeSignals     int
	MinTCCPercent           int
	MinCohesionMethods      int
	MinCohesionFields       int
	MinComponentMethods     int
	MinImportClusterMethods int
	DisabledChecks          []CheckID

	// OCP
	MaxTypeSwitchCases             int // flag type switches / long if-else type-assertion chains
	OCPMinDispatchSites            int
	OCPMinSharedVariants           int
	OCPDispatchOverlapPercent      int
	OCPMinConcreteParameterMethods int
	OCPMinImplementationImports    int
	OCPMinParallelFunctions        int
	OCPMinParallelNodes            int
	OCPParallelSimilarityPercent   int
	OCPDiscriminatorFields         []string
	OCPAllowDispatchTypes          []string
	OCPAllowPackages               []string
	OCPLogicPackages               []string
	OCPImplementationPackages      []string
	OCPCompositionRoots            []string
	ExcludedFiles                  []string

	// ISP
	MaxInterfaceMethods  int // flag interfaces with more methods than this
	ISPMinMethods        int // minimum interface method count for usage-ratio and stub checks
	ISPUsageRatioPercent int // flag when a client uses fewer than this percent of interface methods

	// DIPAllowDependencies lists concrete type names intentionally permitted
	// at composition boundaries (for example a database driver).
	DIPAllowDependencies []string

	// DIPCompositionRootFields suppresses field-level concrete-dependency
	// findings when a struct already wires this many concrete collaborators
	// (typical composition roots).
	DIPCompositionRootFields int

	// DIPInfraErrorPackages lists import paths whose sentinel errors must not
	// appear in logic packages (for example database/sql).
	DIPInfraErrorPackages []string

	// DIPTransportTypes lists fully-qualified transport types that must not
	// appear in logic-package signatures (for example net/http.Request).
	DIPTransportTypes []string
}

Config holds the tunable thresholds for every rule. Sensible defaults are provided by DefaultConfig(); every value can be overridden from the CLI.

func DefaultConfig

func DefaultConfig() Config

DefaultConfig returns the recommended default thresholds.

type FileConfig

type FileConfig struct {
	Profile                   Profile
	EnabledRules              []string
	EnabledChecks             []string
	Excludes                  []string
	Thresholds                map[string]int
	Severities                map[string]Severity
	AllowDependencies         []string
	DisabledChecks            []string
	FailLevel                 Severity
	OCPDiscriminatorFields    []string
	OCPAllowDispatchTypes     []string
	OCPAllowPackages          []string
	OCPLogicPackages          []string
	OCPImplementationPackages []string
	OCPCompositionRoots       []string
	DIPInfraErrorPackages     []string
	DIPTransportTypes         []string
}

FileConfig is the intentionally small .solidify.yml configuration surface.

func LoadFileConfig

func LoadFileConfig(path string) (FileConfig, error)

func (FileConfig) Apply

func (c FileConfig) Apply(cfg *Config)

type Issue

type Issue struct {
	Rule     Rule
	Check    CheckID
	Severity Severity
	Pos      token.Position
	End      token.Position // zero when unknown
	Message  string
	// Evidence is a concise machine-readable explanation of the matched
	// construct. It is intentionally stable so JSON/SARIF consumers can use
	// it without parsing the human-facing message.
	Evidence       string
	Subject        string
	Identity       string
	Metrics        []Metric
	Groups         []SymbolGroup
	Related        []RelatedLocation
	SuggestedFixes []SuggestedFix
	// contains filtered or unexported fields
}

Issue is a single finding reported by one of the rules.

func CheckDIP

func CheckDIP(fset *token.FileSet, files []*ast.File, cfg Config) []Issue

CheckDIP flags struct fields that depend directly on another *concrete* type declared in the same source set, instead of on an interface/ abstraction. High-level types wiring themselves directly to low-level concrete implementations is exactly what "depend on abstractions, not concretions" warns against — it makes the high-level type impossible to reuse or test without dragging the concrete dependency along.

This is necessarily a local, syntax-only heuristic (no go/packages, no type-checking): it only "knows about" types declared in the files being linted, so it can't see through interfaces or types from other packages. That keeps the tool dependency-free; it trades recall for zero setup.

func CheckDIPProgram

func CheckDIPProgram(pkgs []*packageFiles, cfg Config) []Issue

CheckDIPProgram runs architecture-aware DIP checks that need package imports, module paths, or cross-file type information.

func CheckDIPWithTypes

func CheckDIPWithTypes(fset *token.FileSet, files []*ast.File, info *types.Info, cfg Config, pkg *packageFiles) []Issue

func CheckISP

func CheckISP(fset *token.FileSet, files []*ast.File, cfg Config) []Issue

CheckISP flags interfaces that are too big. A "fat" interface forces every implementer to provide methods it may not need, and forces every consumer to depend on methods it never calls — the opposite of what ISP asks for ("many client-specific interfaces are better than one general purpose interface").

func CheckISPWithTypes

func CheckISPWithTypes(fset *token.FileSet, files []*ast.File, info *types.Info, cfg Config, pkg *packageFiles) []Issue

CheckISPWithTypes includes complete embedded method sets when type information is available and retains a local-AST fallback otherwise.

func CheckLSP

func CheckLSP(fset *token.FileSet, files []*ast.File, cfg Config) []Issue

CheckLSP is retained for callers that only have syntax. LSP checks rely on resolved types and deliberately make no claim when type information is not available.

func CheckLSPProgram

func CheckLSPProgram(pkgs []*packageFiles, cfg Config) []Issue

CheckLSPProgram performs checks that need the entire loaded workspace. It intentionally reports a possible nil embedded interface only when no non-nil initialization is visible anywhere in that workspace.

func CheckLSPWithTypes

func CheckLSPWithTypes(fset *token.FileSet, files []*ast.File, info *types.Info, cfg Config, pkg *packageFiles) []Issue

CheckLSPWithTypes performs package-local, contract-backed checks. It does not duplicate unsupported-operation detection: that remains an ISP concern because it identifies interfaces that force a type to implement an operation it does not support.

func CheckOCP

func CheckOCP(fset *token.FileSet, files []*ast.File, cfg Config) []Issue

CheckOCP retains the package-local API used by the focused unit tests. The CLI and Run use CheckOCPProgram so dispatch families can span packages.

func CheckOCPProgram

func CheckOCPProgram(pkgs []*packageFiles, cfg Config) []Issue

CheckOCPProgram runs all OCP checks over one consistent package universe.

func CheckSRP

func CheckSRP(fset *token.FileSet, files []*ast.File, cfg Config) []Issue

CheckSRP runs syntax-only SRP checks. Type-dependent strict checks are intentionally unavailable through this compatibility entry point.

func CheckSRPWithTypes

func CheckSRPWithTypes(in SRPCheckInput) []Issue

CheckSRPWithTypes combines the always-available syntax checks with the package-wide metrics that need a complete type graph. A syntax-only run deliberately emits advisory findings but never guesses at strict cohesion or god-type violations.

func Run

func Run(pkgs []*packageFiles, cfg Config, enabled map[Rule]bool) []Issue

Run executes every registered check against loaded packages and returns all issues, sorted by file/line for stable, readable output.

func (Issue) AnalysisRoot

func (i Issue) AnalysisRoot() string

AnalysisRoot returns the canonical analysis root used for portable paths.

func (Issue) Fingerprint

func (i Issue) Fingerprint() string

Fingerprint is stable across line-only changes and is suitable for baselines.

func (Issue) ID

func (i Issue) ID() string

ID identifies the specific design smell behind a rule finding.

func (Issue) PortablePath

func (i Issue) PortablePath() string

PortablePath returns the normalized machine-facing path for this finding.

func (Issue) PortableURI

func (i Issue) PortableURI() string

PortableURI returns the SARIF artifact URI for this finding.

func (Issue) PrimaryLocationLineHash

func (i Issue) PrimaryLocationLineHash() string

PrimaryLocationLineHash returns a stable line hash for SARIF consumers.

func (Issue) String

func (i Issue) String() string

type Maturity

type Maturity string

Maturity controls whether a check participates in the conservative default profile or requires an explicit experimental opt-in.

const (
	MaturityStable       Maturity = "stable"
	MaturityExperimental Maturity = "experimental"
)

type Metric

type Metric struct {
	Name       string  `json:"name"`
	Value      float64 `json:"value"`
	Threshold  float64 `json:"threshold,omitempty"`
	Comparator string  `json:"comparator,omitempty"`
}

type PackageSnapshot

type PackageSnapshot struct {
	// contains filtered or unexported fields
}

PackageSnapshot exposes loaded package state to external analysis drivers.

func SnapshotFromPackages

func SnapshotFromPackages(pkg *packages.Package) *PackageSnapshot

SnapshotFromPackages converts a go/packages entry into a snapshot.

func SnapshotFromSyntax

func SnapshotFromSyntax(fset *token.FileSet, files []*ast.File, info *types.Info, typeComplete bool) *PackageSnapshot

SnapshotFromSyntax builds a package snapshot for go/analysis bridges.

func (*PackageSnapshot) RunDIP

func (p *PackageSnapshot) RunDIP(cfg Config) []Issue

RunDIP executes package-scoped DIP checks on the snapshot.

func (*PackageSnapshot) RunISP

func (p *PackageSnapshot) RunISP(cfg Config) []Issue

RunISP executes package-scoped ISP checks on the snapshot.

func (*PackageSnapshot) RunLSP

func (p *PackageSnapshot) RunLSP(cfg Config) []Issue

RunLSP executes the package-scoped non-exact-EOF check on the snapshot.

func (*PackageSnapshot) RunSRP

func (p *PackageSnapshot) RunSRP(cfg Config) []Issue

RunSRP executes all nine package-scoped SRP checks on the snapshot.

type Profile

type Profile string

Profile names a public rule-maturity selection.

const (
	ProfileStable Profile = "stable"
	ProfileAll    Profile = "all"
)

type RelatedLocation

type RelatedLocation struct {
	Pos     token.Position `json:"position"`
	Message string         `json:"message,omitempty"`
}

type Rule

type Rule string

Rule identifies which SOLID letter (and sub-check) produced an issue.

const (
	RuleSRP Rule = "SOLID-S" // Single Responsibility Principle
	RuleOCP Rule = "SOLID-O" // Open/Closed Principle
	RuleLSP Rule = "SOLID-L" // Liskov Substitution Principle
	RuleISP Rule = "SOLID-I" // Interface Segregation Principle
	RuleDIP Rule = "SOLID-D" // Dependency Inversion Principle
)

type SRPCheckInput

type SRPCheckInput struct {
	Fset         *token.FileSet
	Files        []*ast.File
	Info         *types.Info
	Pkg          *types.Package
	TypeComplete bool
	Config       Config
	PkgFiles     *packageFiles
}

SRPCheckInput groups the package context for SRP analysis.

type Scope

type Scope int

Scope distinguishes package-local checks from whole-program correlation.

const (
	ScopePackage Scope = iota
	ScopeProgram
)

type Severity

type Severity string

Severity of a reported issue.

const (
	SeverityNote    Severity = "note"
	SeverityWarning Severity = "warning"
	SeverityError   Severity = "error"
)

type SuggestedFix

type SuggestedFix struct {
	Message string
	Edits   []TextEdit
}

SuggestedFix groups optional text edits for a finding.

func IgnoreSuppressionFix

func IgnoreSuppressionFix(issue Issue, reason string) SuggestedFix

IgnoreSuppressionFix returns a mechanical suggested fix that inserts a justified suppression comment on the line above a finding.

type Surface

type Surface uint8

Surface identifies a supported solidlint integration.

const (
	SurfaceCLI Surface = 1 << iota
	SurfaceModulePlugin
	SurfaceGoPlugin
)

func (Surface) Supports

func (s Surface) Supports(surface Surface) bool

type SymbolGroup

type SymbolGroup struct {
	Label   string   `json:"label"`
	Symbols []string `json:"symbols"`
}

type SyntaxSupport

type SyntaxSupport string

SyntaxSupport defines what a check may do without complete go/types facts.

const (
	SyntaxEquivalent   SyntaxSupport = "equivalent"
	SyntaxConservative SyntaxSupport = "conservative"
	SyntaxUnavailable  SyntaxSupport = "unavailable"
)

type TextEdit

type TextEdit struct {
	Filename string
	Start    token.Position
	End      token.Position
	NewText  string
}

TextEdit is a mechanical source edit suggested for a finding.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL