Documentation
¶
Index ¶
- func InertStmt(info *types.Info, node ast.Node) bool
- func IntervalInert(info *types.Info, parent inspector.Cursor, absorbedDecls []astutil.NodeIndex, ...) bool
- func SafetyCheck(info *types.Info, decl inspector.Cursor, declScope, targetScope *types.Scope, ...) category.MoveStatus
- type CandidateManager
- func (cm CandidateManager) AddCandidate(decl astutil.NodeIndex, m MoveCandidate)
- func (cm CandidateManager) BlockMovesLosingTypeInfo(allDeclarations iter.Seq2[*types.Var, []usage.DeclarationNode]) map[astutil.NodeIndex][]*types.Var
- func (cm CandidateManager) BlockMovesWithTypeChanges(allDeclarations iter.Seq2[*types.Var, []usage.DeclarationNode])
- func (cm CandidateManager) MarkSideEffects(info *types.Info, body inspector.Cursor)
- func (cm CandidateManager) OrphanedDeclarations(allDeclarations iter.Seq2[*types.Var, []usage.DeclarationNode]) map[astutil.NodeIndex][]*types.Var
- func (cm CandidateManager) ResolveInitFieldConflicts(in *inspector.Inspector, combine bool)
- func (cm CandidateManager) SortedMoveTargets(unused, orphanedDeclarations map[astutil.NodeIndex][]*types.Var) []MoveTarget
- type MovableDecl
- type MoveCandidate
- type MoveTarget
- type Stage
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func InertStmt ¶ added in v0.0.7
InertStmt determines if a statement is "inert", meaning it has no side effects or observable interactions.
func IntervalInert ¶ added in v0.0.7
func IntervalInert(info *types.Info, parent inspector.Cursor, absorbedDecls []astutil.NodeIndex, start, end token.Pos) bool
IntervalInert checks whether the execution interval [start, end) is inert.
An interval is considered inert if it contains no statements that might have side effects or observable interactions with the moved code.
Specifically, it returns false if the interval contains:
- Assignments or reassignments to existing variables (side effects)
- Function calls or other expressions that are not pure/constant
- Branching or control flow statements (other than those implicitly handled)
Pure declarations (var, const, type) and short variable declarations of *new* variables initialized with constant expressions and no function calls are considered inert.
The check covers the interval [start, end), excluding the end position.
Types ¶
type CandidateManager ¶
type CandidateManager struct {
// contains filtered or unexported fields
}
CandidateManager manages the set of declaration move candidates.
func NewManager ¶ added in v0.0.7
func NewManager() CandidateManager
NewManager creates a CandidateManager.
func (CandidateManager) AddCandidate ¶ added in v0.0.7
func (cm CandidateManager) AddCandidate(decl astutil.NodeIndex, m MoveCandidate)
AddCandidate adds candidate using the given node index and move candidate data.
func (CandidateManager) BlockMovesLosingTypeInfo ¶
func (cm CandidateManager) BlockMovesLosingTypeInfo(allDeclarations iter.Seq2[*types.Var, []usage.DeclarationNode]) map[astutil.NodeIndex][]*types.Var
BlockMovesLosingTypeInfo prevents moves that would lose necessary type information.
Scenario: A variable is declared with an explicit or inferred type, then later reassigned with a different type inference. If we move the first declaration, subsequent uses would have a different type.
Example:
var x any // First declaration (unused) x, y := "hello", 0 // Reassignment with different type
Moving the first declaration would change x's type from any to string.
func (CandidateManager) BlockMovesWithTypeChanges ¶
func (cm CandidateManager) BlockMovesWithTypeChanges(allDeclarations iter.Seq2[*types.Var, []usage.DeclarationNode])
BlockMovesWithTypeChanges marks candidates as blocked when moving would change the inferred type of a variable that is actually used.
func (CandidateManager) MarkSideEffects ¶ added in v0.0.7
func (cm CandidateManager) MarkSideEffects(info *types.Info, body inspector.Cursor)
MarkSideEffects marks candidates as blocked if there are intervening statements with possible side effects.
func (CandidateManager) OrphanedDeclarations ¶
func (cm CandidateManager) OrphanedDeclarations(allDeclarations iter.Seq2[*types.Var, []usage.DeclarationNode]) map[astutil.NodeIndex][]*types.Var
OrphanedDeclarations identifies declarations that would become unused after other declarations are moved. These need their variables replaced with '_'.
This handles the case where a variable is reassigned multiple times, and moving the first declaration leaves subsequent assignments with no remaining reads.
func (CandidateManager) ResolveInitFieldConflicts ¶
func (cm CandidateManager) ResolveInitFieldConflicts(in *inspector.Inspector, combine bool)
ResolveInitFieldConflicts handles multiple declarations targeting the same init field.
It attempts to combine compatible simple assignments (x := 1; y := 2 -> x, y := 1, 2).
func (CandidateManager) SortedMoveTargets ¶
func (cm CandidateManager) SortedMoveTargets(unused, orphanedDeclarations map[astutil.NodeIndex][]*types.Var) []MoveTarget
SortedMoveTargets converts the intermediate candidate map to a sorted slice of MoveTarget.
Combines:
- Regular move candidates (with or without unused variables)
- Orphaned declarations (no target node, all variables unused)
Returns results sorted by source position for deterministic output.
type MovableDecl ¶
type MovableDecl struct {
Unused []string // Unused identifiers in this declaration
Decl astutil.NodeIndex // Inspector index of the declaration statement to move
}
MovableDecl represents a declaration that can be moved to another scope in the code analysis process.
type MoveCandidate ¶
type MoveCandidate struct {
TargetNode ast.Node // Destination AST node (e.g., *ast.IfStmt for init field, *ast.BlockStmt for block)
AbsorbedDecls []astutil.NodeIndex // Additional declarations merged into this one
Status category.MoveStatus // Whether the move is safe (MoveAllowed) or blocked (with reason)
}
MoveCandidate is an intermediate representation of a potential move operation.
Differences from MoveTarget:
- Does not include the declaration index (stored as a map key)
- Mutable status field (updated during conflict resolution)
type MoveTarget ¶
type MoveTarget struct {
AbsorbedDecls []MovableDecl // Additional declarations merged into this one
TargetNode ast.Node // The node with the target scope (e.g., *[ast.IfStmt], *[ast.BlockStmt])
MovableDecl // The declaration to move
MoveStatus category.MoveStatus // Status indicating if the move is safe or why it isn't
}
MoveTarget represents a declaration that can be moved to a tighter scope.
type Stage ¶
type Stage struct {
// The current [*analysis.Pass]
*analysis.Pass
// TargetScope provides context for scope adjustments and safety checks.
scope.TargetScope
// contains filtered or unexported fields
}
Stage contains configurable options for analyzing variable scope tightening.
func New ¶ added in v0.0.5
New creates a target.Stage.
func (Stage) CollectCandidates ¶ added in v0.0.7
func (ts Stage) CollectCandidates(cm CandidateManager, body inspector.Cursor, cf astutil.CurrentFile, scopeRanges iter.Seq2[astutil.NodeIndex, usage.ScopeRange])
CollectCandidates iterates through all usage scopes and determines valid target nodes for declarations that can be moved to tighter scopes.
func (Stage) SelectTargets ¶
func (ts Stage) SelectTargets(ctx context.Context, cf astutil.CurrentFile, body inspector.Cursor, usageData usage.Result) []MoveTarget
SelectTargets determines which declarations can be moved to tighter scopes and where they should go.
Returns a sorted list of move targets.