Execution Paths
The path generator enumerates every distinct execution path through your Effect program. Each path represents a unique sequence of steps that could execute given certain conditions - which branches are taken, which errors occur, and how loops iterate.
Generating Paths
Section titled “Generating Paths”The mermaid-paths format renders each execution path as a separate diagram:
npx effect-analyze ./src/transfer.ts --format mermaid-pathsLibrary API
Section titled “Library API”import { analyze, generatePaths } from "effect-analyzer"import { Effect } from "effect"
const ir = await Effect.runPromise(analyze("./src/transfer.ts").single())const paths = generatePaths(ir)
for (const path of paths) { console.log(`Path: ${path.steps.map(s => s.name ?? s.nodeId).join(" → ")}`) console.log(` Conditions: ${path.conditions.length}`) console.log(` Has loops: ${path.hasLoops}`)}Each EffectPath contains:
| Field | Type | Description |
|---|---|---|
steps | PathStepRef[] | Ordered sequence of steps in this path |
conditions | PathCondition[] | Conditions that must hold for this path to execute |
hasLoops | boolean | Whether this path passes through a loop |
Each PathStepRef includes:
| Field | Type | Description |
|---|---|---|
nodeId | string | Reference to the IR node |
name | string | undefined | Human-readable step name |
repeated | boolean | Whether this step repeats (loop body) |
Options
Section titled “Options”Control path generation with PathGeneratorOptions:
const paths = generatePaths(ir, { maxPaths: 100, // Cap at 100 paths (default: 1000) expandLoops: true, // Expand loop bodies into separate paths maxLoopIterations: 3 // Maximum loop unrolling depth (default: 3)})| Option | Type | Default | Description |
|---|---|---|---|
maxPaths | number | 1000 | Maximum paths to generate before stopping |
expandLoops | boolean | false | Expand loop iterations as separate paths |
maxLoopIterations | number | 3 | How many iterations to unroll when expandLoops is true |
Path Metadata
Section titled “Path Metadata”Use generatePathsWithMetadata for additional information:
import { generatePathsWithMetadata } from "effect-analyzer"
const result = generatePathsWithMetadata(ir, { maxPaths: 50 })
console.log(result.paths.length) // Number of paths generatedconsole.log(result.limitHit) // true if maxPaths was reachedCalculating Path Statistics
Section titled “Calculating Path Statistics”Use calculatePathStatistics to get aggregate statistics across all paths:
import { generatePaths, calculatePathStatistics } from "effect-analyzer"
const paths = generatePaths(ir)const stats = calculatePathStatistics(paths)
console.log(stats.totalPaths) // Total number of pathsconsole.log(stats.avgPathLength) // Average steps per pathconsole.log(stats.maxPathLength) // Longest pathconsole.log(stats.pathsWithLoops) // How many paths include loopsconsole.log(stats.uniqueConditions) // Distinct branching conditionsFiltering Paths
Section titled “Filtering Paths”Use filterPaths to narrow down to specific paths of interest:
import { generatePaths, filterPaths } from "effect-analyzer"
const paths = generatePaths(ir)
// Filter to paths that include a specific stepconst withDebit = filterPaths(paths, { includeStep: "debit",})
// Filter to paths with error conditionsconst errorPaths = filterPaths(paths, { hasErrors: true,})From Paths to Tests
Section titled “From Paths to Tests”Paths are the input to the Test Coverage Matrix. Each path becomes a test case describing what conditions to set up and what steps to verify.
import { generatePaths, generateTestMatrix } from "effect-analyzer"
const paths = generatePaths(ir)const matrix = generateTestMatrix(paths)Related
Section titled “Related”- Complexity Metrics -
pathCountmetric fromcalculateComplexity - Test Coverage Matrix - generate test cases from paths
- All Formats -
mermaid-pathsformat reference