Documentation
¶
Overview ¶
Package analysis finds unhandled error sites and analyzes interface compliance.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func GenerateUniqueName ¶
GenerateUniqueName generates a variable name that does not collide with existing names in the provided scope or its parent scopes.
It starts with the base name. If that name resolves to an object in the scope (or parents), it appends a counter (e.g., "err" -> "err1") and retries until a unique name is found.
scope: The local scope where the variable handles are checked. base: The preferred name (e.g., "err").
Returns "base" if it's not present, otherwise "base1", "base2", etc.
Types ¶
type ErrcheckParser ¶
type ErrcheckParser struct {
// contains filtered or unexported fields
}
ErrcheckParser provides functionality to parse text output from the 'errcheck' tool and convert it into structured InjectionPoints for refactoring.
func NewErrcheckParser ¶
func NewErrcheckParser(pkgs []*packages.Package) *ErrcheckParser
NewErrcheckParser initializes a parser by indexing the provided loaded packages.
pkgs: The packages loaded by the loader that correspond to the analysis target.
func (*ErrcheckParser) Parse ¶
func (p *ErrcheckParser) Parse(reader io.Reader) ([]InjectionPoint, error)
Parse reads the errcheck output from the provided reader and generates injection points.
reader: Source of the errcheck stdout (e.g. strings.NewReader or os.Stdin).
Returns a slice of valid InjectionPoints where unhandled errors were reported. Lines that cannot be parsed or point to files not currently loaded are skipped silently or with a warning depending on implementation desires (current: skip).
type InjectionPoint ¶
type InjectionPoint struct {
// Pkg is the package containing the code.
Pkg *packages.Package
// File is the AST file containing the statement.
File *ast.File
// Call is the function call expression returning the error.
Call *ast.CallExpr
// Assign is the assignment statement (e.g., "_ = foo()"). Nil if it's a bare expression, defer, go, or gen decl.
// If the call is inside a composite literal, Assign points to the statement holding the literal (if AssignStmt).
Assign *ast.AssignStmt
// Stmt is the statement wrapping the call.
// Can be *ast.ExprStmt, *ast.AssignStmt, *ast.DeferStmt, *ast.GoStmt, *ast.IfStmt, *ast.SwitchStmt, *ast.ReturnStmt, or nil for Global Decls.
Stmt ast.Stmt
// Pos is the position of the error return (usually the call site).
Pos token.Pos
}
InjectionPoint represents a location in the code where an error is unhandled.
func Detect ¶
Detect scans the provided packages for unhandled errors. It detects calls processing errors that are ignored via blank identifier, treated as expression statements, ignored in defer/go statements, embedded in control structures, ignored in global variable initializers, hidden within method chains (`foo().bar()`), or embedded in composite literals.
It respects the "// auto-err:ignore" directive. If this text appears in comments associated with the statement, the injection point is skipped.
pkgs: The list of packages to analyze. flt: The filter rules to exclude specific files or symbols. debug: If true, prints verbose reasons why calls are ignored.
Returns a slice of detected points where error handling is missing.
type InterfaceConflict ¶
type InterfaceConflict struct {
// Method is the function being refactored.
Method *types.Func
// Interface is the named interface that would be broken.
Interface *types.TypeName
// InterfaceMethod is the specific method definition within the interface that conflicts.
InterfaceMethod *types.Func
}
InterfaceConflict represents a detected conflict where refactoring a function would break the implementation of an interface.
func (InterfaceConflict) Error ¶
func (c InterfaceConflict) Error() string
Error formats the conflict into a readable string.
type InterfaceRegistry ¶
type InterfaceRegistry struct {
// contains filtered or unexported fields
}
InterfaceRegistry maintains a cache of all visible interface definitions across the loaded packages and their transitive dependencies.
It is used to perform quick lookups when determining if a method refactor is safe to perform.
func NewInterfaceRegistry ¶
func NewInterfaceRegistry(pkgs []*packages.Package) *InterfaceRegistry
NewInterfaceRegistry initializes a registry and populates it by scanning the provided packages and their dependencies for named interface definitions.
pkgs: The entry point packages loaded by the tool.
Returns a fully populated InterfaceRegistry.
func (*InterfaceRegistry) CheckCompliance ¶
func (r *InterfaceRegistry) CheckCompliance(method *types.Func) ([]InterfaceConflict, error)
CheckCompliance verifies if refactoring the given method would violate any interface implementations found in the registry.
A conflict exists if: 1. The method's receiver type currently implements an interface `I`. 2. `I` explicitly defines a method with the same name as `method`.
method: The function object being targeted for refactoring (must be a method).
Returns a slice of InterfaceConflict if issues are found, or nil if safe.