analyzer

package
v0.1.0-alpha Latest Latest
Warning

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

Go to latest
Published: Nov 27, 2025 License: MIT Imports: 8 Imported by: 0

Documentation

Index

Constants

View Source
const (
	LabelFunctionBody = "func_body"
	LabelClassBody    = "class_body"
	LabelUnreachable  = "unreachable"
	LabelMainModule   = "main"
	LabelEntry        = "ENTRY"
	LabelExit         = "EXIT"

	// Loop-related labels
	LabelLoopHeader = "loop_header"
	LabelLoopBody   = "loop_body"
	LabelLoopExit   = "loop_exit"

	// Exception-related labels
	LabelTryBlock     = "try_block"
	LabelCatchBlock   = "catch_block"
	LabelFinallyBlock = "finally_block"

	// Switch-related labels
	LabelSwitchCase  = "switch_case"
	LabelSwitchMerge = "switch_merge"
)

Block label constants

Variables

This section is empty.

Functions

func CalculateNestingDepth

func CalculateNestingDepth(node *parser.Node) int

CalculateNestingDepth calculates the maximum nesting depth of a function

func DetectAll

func DetectAll(cfgs map[string]*CFG, filePath string) map[string]*DeadCodeResult

DetectAll analyzes dead code for all functions in a file

Types

type BasicBlock

type BasicBlock struct {
	// ID is the unique identifier for this block
	ID string

	// Statements contains the AST nodes in this block
	Statements []*parser.Node

	// Predecessors are blocks that can flow into this block
	Predecessors []*Edge

	// Successors are blocks that this block can flow to
	Successors []*Edge

	// Label is an optional human-readable label
	Label string

	// IsEntry indicates if this is an entry block
	IsEntry bool

	// IsExit indicates if this is an exit block
	IsExit bool
}

BasicBlock represents a basic block in the control flow graph

func NewBasicBlock

func NewBasicBlock(id string) *BasicBlock

NewBasicBlock creates a new basic block with the given ID

func (*BasicBlock) AddStatement

func (bb *BasicBlock) AddStatement(stmt *parser.Node)

AddStatement adds an AST node to this block

func (*BasicBlock) AddSuccessor

func (bb *BasicBlock) AddSuccessor(to *BasicBlock, edgeType EdgeType) *Edge

AddSuccessor adds an outgoing edge to another block

func (*BasicBlock) IsEmpty

func (bb *BasicBlock) IsEmpty() bool

IsEmpty returns true if the block has no statements

func (*BasicBlock) RemoveSuccessor

func (bb *BasicBlock) RemoveSuccessor(to *BasicBlock)

RemoveSuccessor removes an edge to the specified block

func (*BasicBlock) String

func (bb *BasicBlock) String() string

String returns a string representation of the basic block

type CFG

type CFG struct {
	// Entry is the entry point of the graph
	Entry *BasicBlock

	// Exit is the exit point of the graph
	Exit *BasicBlock

	// Blocks contains all blocks in the graph, indexed by ID
	Blocks map[string]*BasicBlock

	// Name is the name of the CFG (e.g., function name)
	Name string

	// FunctionNode is the original AST node for the function
	FunctionNode *parser.Node
	// contains filtered or unexported fields
}

CFG represents a control flow graph

func NewCFG

func NewCFG(name string) *CFG

NewCFG creates a new control flow graph

func (*CFG) AddBlock

func (cfg *CFG) AddBlock(block *BasicBlock)

AddBlock adds an existing block to the graph

func (*CFG) BreadthFirstWalk

func (cfg *CFG) BreadthFirstWalk(visitor CFGVisitor)

BreadthFirstWalk performs a breadth-first traversal of the CFG

func (*CFG) ConnectBlocks

func (cfg *CFG) ConnectBlocks(from, to *BasicBlock, edgeType EdgeType) *Edge

ConnectBlocks creates an edge between two blocks

func (*CFG) CreateBlock

func (cfg *CFG) CreateBlock(label string) *BasicBlock

CreateBlock creates a new basic block and adds it to the graph

func (*CFG) GetBlock

func (cfg *CFG) GetBlock(id string) *BasicBlock

GetBlock retrieves a block by its ID

func (*CFG) RemoveBlock

func (cfg *CFG) RemoveBlock(block *BasicBlock)

RemoveBlock removes a block from the graph

func (*CFG) Size

func (cfg *CFG) Size() int

Size returns the number of blocks in the graph

func (*CFG) String

func (cfg *CFG) String() string

String returns a string representation of the CFG

func (*CFG) Walk

func (cfg *CFG) Walk(visitor CFGVisitor)

Walk performs a depth-first traversal of the CFG

type CFGBuilder

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

CFGBuilder builds control flow graphs from AST nodes

func NewCFGBuilder

func NewCFGBuilder() *CFGBuilder

NewCFGBuilder creates a new CFG builder

func (*CFGBuilder) Build

func (b *CFGBuilder) Build(node *parser.Node) (*CFG, error)

Build constructs a CFG from an AST node

func (*CFGBuilder) BuildAll

func (b *CFGBuilder) BuildAll(node *parser.Node) (map[string]*CFG, error)

BuildAll builds CFGs for all functions in the AST

func (*CFGBuilder) SetLogger

func (b *CFGBuilder) SetLogger(logger *log.Logger)

SetLogger sets an optional logger for error reporting

type CFGVisitor

type CFGVisitor interface {
	// VisitBlock is called for each basic block
	// Returns false to stop traversal
	VisitBlock(block *BasicBlock) bool

	// VisitEdge is called for each edge
	// Returns false to stop traversal
	VisitEdge(edge *Edge) bool
}

CFGVisitor defines the interface for visiting CFG nodes

type ComplexityAnalyzer

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

ComplexityAnalyzer analyzes complexity for multiple functions

func NewComplexityAnalyzer

func NewComplexityAnalyzer(cfg *config.ComplexityConfig) *ComplexityAnalyzer

NewComplexityAnalyzer creates a new complexity analyzer

func (*ComplexityAnalyzer) AnalyzeFile

func (ca *ComplexityAnalyzer) AnalyzeFile(ast *parser.Node) ([]*ComplexityResult, error)

AnalyzeFile analyzes complexity for all functions in a file

type ComplexityResult

type ComplexityResult struct {
	// McCabe cyclomatic complexity
	Complexity int

	// Raw CFG metrics
	Edges               int
	Nodes               int
	ConnectedComponents int

	// Function/method information
	FunctionName string
	StartLine    int
	StartCol     int
	EndLine      int

	// Nesting depth
	NestingDepth int

	// Decision points breakdown
	IfStatements      int
	LoopStatements    int
	ExceptionHandlers int
	SwitchCases       int
	LogicalOperators  int // JavaScript-specific: &&, ||, ??
	TernaryOperators  int // JavaScript-specific: ? :

	// Risk assessment based on complexity thresholds
	RiskLevel string // "low", "medium", "high"
}

ComplexityResult holds cyclomatic complexity metrics for a function or method

func CalculateComplexity

func CalculateComplexity(cfg *CFG) *ComplexityResult

CalculateComplexity computes McCabe cyclomatic complexity for a CFG using default thresholds

func CalculateComplexityWithConfig

func CalculateComplexityWithConfig(cfg *CFG, complexityConfig *config.ComplexityConfig) *ComplexityResult

CalculateComplexityWithConfig computes McCabe cyclomatic complexity using provided configuration

func (*ComplexityResult) GetComplexity

func (cr *ComplexityResult) GetComplexity() int

func (*ComplexityResult) GetDetailedMetrics

func (cr *ComplexityResult) GetDetailedMetrics() map[string]int

func (*ComplexityResult) GetFunctionName

func (cr *ComplexityResult) GetFunctionName() string

func (*ComplexityResult) GetRiskLevel

func (cr *ComplexityResult) GetRiskLevel() string

func (*ComplexityResult) String

func (cr *ComplexityResult) String() string

String returns a human-readable representation of the complexity result

type DeadCodeDetector

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

DeadCodeDetector provides high-level dead code detection functionality

func NewDeadCodeDetector

func NewDeadCodeDetector(cfg *CFG) *DeadCodeDetector

NewDeadCodeDetector creates a new dead code detector for the given CFG

func NewDeadCodeDetectorWithFilePath

func NewDeadCodeDetectorWithFilePath(cfg *CFG, filePath string) *DeadCodeDetector

NewDeadCodeDetectorWithFilePath creates a new dead code detector with file path context

func (*DeadCodeDetector) Detect

func (dcd *DeadCodeDetector) Detect() *DeadCodeResult

Detect performs dead code detection and returns structured findings

type DeadCodeFinding

type DeadCodeFinding struct {
	// Function information
	FunctionName string `json:"function_name"`
	FilePath     string `json:"file_path"`

	// Location information
	StartLine int `json:"start_line"`
	EndLine   int `json:"end_line"`

	// Dead code details
	BlockID     string         `json:"block_id"`
	Code        string         `json:"code"`
	Reason      DeadCodeReason `json:"reason"`
	Severity    SeverityLevel  `json:"severity"`
	Description string         `json:"description"`

	// Context information
	Context []string `json:"context,omitempty"`
}

DeadCodeFinding represents a single dead code detection result

type DeadCodeReason

type DeadCodeReason string

DeadCodeReason represents the reason why code is considered dead

const (
	// ReasonUnreachableAfterReturn indicates code after a return statement
	ReasonUnreachableAfterReturn DeadCodeReason = "unreachable_after_return"

	// ReasonUnreachableAfterBreak indicates code after a break statement
	ReasonUnreachableAfterBreak DeadCodeReason = "unreachable_after_break"

	// ReasonUnreachableAfterContinue indicates code after a continue statement
	ReasonUnreachableAfterContinue DeadCodeReason = "unreachable_after_continue"

	// ReasonUnreachableAfterThrow indicates code after a throw statement
	ReasonUnreachableAfterThrow DeadCodeReason = "unreachable_after_throw"

	// ReasonUnreachableBranch indicates an unreachable branch condition
	ReasonUnreachableBranch DeadCodeReason = "unreachable_branch"

	// ReasonUnreachableAfterInfiniteLoop indicates code after an infinite loop
	ReasonUnreachableAfterInfiniteLoop DeadCodeReason = "unreachable_after_infinite_loop"
)

type DeadCodeResult

type DeadCodeResult struct {
	// Function information
	FunctionName string `json:"function_name"`
	FilePath     string `json:"file_path"`

	// Analysis results
	Findings       []*DeadCodeFinding `json:"findings"`
	TotalBlocks    int                `json:"total_blocks"`
	DeadBlocks     int                `json:"dead_blocks"`
	ReachableRatio float64            `json:"reachable_ratio"`

	// Performance metrics
	AnalysisTime time.Duration `json:"analysis_time"`
}

DeadCodeResult contains the results of dead code analysis for a single CFG

func (*DeadCodeResult) GetCriticalFindings

func (dcr *DeadCodeResult) GetCriticalFindings() []*DeadCodeFinding

GetCriticalFindings returns only critical severity findings

func (*DeadCodeResult) GetWarningFindings

func (dcr *DeadCodeResult) GetWarningFindings() []*DeadCodeFinding

GetWarningFindings returns only warning severity findings

func (*DeadCodeResult) HasFindings

func (dcr *DeadCodeResult) HasFindings() bool

HasFindings returns true if there are any dead code findings

type Edge

type Edge struct {
	From *BasicBlock
	To   *BasicBlock
	Type EdgeType
}

Edge represents a directed edge between two basic blocks

type EdgeType

type EdgeType int

EdgeType represents the type of edge between basic blocks

const (
	// EdgeNormal represents normal sequential flow
	EdgeNormal EdgeType = iota
	// EdgeCondTrue represents conditional true branch
	EdgeCondTrue
	// EdgeCondFalse represents conditional false branch
	EdgeCondFalse
	// EdgeException represents exception flow
	EdgeException
	// EdgeLoop represents loop back edge
	EdgeLoop
	// EdgeBreak represents break statement flow
	EdgeBreak
	// EdgeContinue represents continue statement flow
	EdgeContinue
	// EdgeReturn represents return statement flow
	EdgeReturn
)

func (EdgeType) String

func (e EdgeType) String() string

String returns string representation of EdgeType

type ReachabilityAnalyzer

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

ReachabilityAnalyzer performs reachability analysis on CFGs

func NewReachabilityAnalyzer

func NewReachabilityAnalyzer(cfg *CFG) *ReachabilityAnalyzer

NewReachabilityAnalyzer creates a new reachability analyzer for the given CFG

func (*ReachabilityAnalyzer) AnalyzeReachability

func (ra *ReachabilityAnalyzer) AnalyzeReachability() *ReachabilityResult

AnalyzeReachability performs reachability analysis starting from the entry block

func (*ReachabilityAnalyzer) AnalyzeReachabilityFrom

func (ra *ReachabilityAnalyzer) AnalyzeReachabilityFrom(startBlock *BasicBlock) *ReachabilityResult

AnalyzeReachabilityFrom performs reachability analysis from a specific starting block

type ReachabilityResult

type ReachabilityResult struct {
	// ReachableBlocks contains blocks that can be reached from entry
	ReachableBlocks map[string]*BasicBlock

	// UnreachableBlocks contains blocks that cannot be reached from entry
	UnreachableBlocks map[string]*BasicBlock

	// TotalBlocks is the total number of blocks analyzed
	TotalBlocks int

	// ReachableCount is the number of reachable blocks
	ReachableCount int

	// UnreachableCount is the number of unreachable blocks
	UnreachableCount int

	// AnalysisTime is the time taken to perform the analysis
	AnalysisTime time.Duration
}

ReachabilityResult contains the results of reachability analysis

func (*ReachabilityResult) GetReachabilityRatio

func (result *ReachabilityResult) GetReachabilityRatio() float64

GetReachabilityRatio returns the ratio of reachable blocks to total blocks

func (*ReachabilityResult) GetUnreachableBlocksWithStatements

func (result *ReachabilityResult) GetUnreachableBlocksWithStatements() map[string]*BasicBlock

GetUnreachableBlocksWithStatements returns unreachable blocks that contain statements

func (*ReachabilityResult) HasUnreachableCode

func (result *ReachabilityResult) HasUnreachableCode() bool

HasUnreachableCode returns true if there are unreachable blocks with statements

type SeverityLevel

type SeverityLevel string

SeverityLevel represents the severity of a dead code finding

const (
	// SeverityLevelCritical indicates code that is definitely unreachable
	SeverityLevelCritical SeverityLevel = "critical"

	// SeverityLevelWarning indicates code that is likely unreachable
	SeverityLevelWarning SeverityLevel = "warning"

	// SeverityLevelInfo indicates potential optimization opportunities
	SeverityLevelInfo SeverityLevel = "info"
)

Jump to

Keyboard shortcuts

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