Caller Path
Understand how the code reached this function. One route at a time.
Place your cursor inside a function and run Show Caller Path. Follow its callers through a compact panel beside your editor, with clickable function names, filenames, and line numbers at every step.
Caller Path uses your installed language provider's semantic information. It works across repositories without project-specific mappings. When the provider cannot establish a connection, the panel explains where tracing stopped.
Quick start
- Open a trusted workspace and let its language extension finish loading.
- Place your cursor anywhere inside a function or method.
- Right-click and choose Show Caller Path, or run that command from the Command Palette.
The How did we get here? panel opens in the Secondary Side Bar. Drag its divider to keep as much room for code as you need.
Follow the route
An illustrative route might look like this; actual names and locations come from your workspace:
runImport
import.ts:12
↓
parseRow
parser.ts:38
↓
normalizeValue
values.ts:9
[You are here]
Click a step to open and highlight its declaration. The displayed route stays in place while you explore it. You are here follows the opened step; Trace target marks the original destination. Back to target returns you there.
The route stays pinned while you click code, select a call, switch files, or hide and reopen the panel. Run Show Caller Path again to trace a different function. Open Other callers to choose an alternative route for the current target. Only one route is shown at a time.
After return (C#)
Select a return statement, or place the cursor inside its catch block, and run Show Caller Path. Open After return to see where that value goes in a chosen caller. If the method has several returns, choose one explicitly.
The panel follows a supported constant null or Boolean result into a direct local assignment, a proven check, and the caller's return or throw. Each step opens its exact source line. The return and caller remain pinned while you explore. Choose another caller to see its own processing.
Null checks include value?.Member == null when the returned value is proven null. This does not infer arbitrary property values or evaluate custom equality operators. A selected throw itself is not a return value; start from the callee's supported return to follow its caller's handling.
This optional adapter requires the .NET 10 SDK, plus an already restored C# project compatible with the installed SDKs. It discovers local SDK installations using PATH, DOTNET_ROOT, and standard installation folders, including /usr/local/share/dotnet on macOS. An SDK does not need to be on the GUI editor's PATH. For a custom location, set Caller Path: Dotnet Path to the absolute dotnet executable. Discovery performs no downloads or settings changes.
The adapter loads real projects locally using bundled Roslyn assemblies. It does not restore or run the application. Project evaluation requires workspace trust because MSBuild can execute project-defined build targets. Missing assets, ambiguous project ownership, compilation problems, unsupported control flow, and unresolved links stop analysis with a message. Unavailable analysis offers Retry and Caller Path settings.
After return is deliberately bounded: it does not generally follow arbitrary values, expression-bodied/local functions, callbacks, loops, LINQ aggregation, reflection, or runtime dispatch. It follows at most 12 direct statements and stops at unsupported branches, finally blocks, or value transformations. Analyzer/source-generator references are disabled; projects requiring generated symbols may be unavailable. Other languages retain caller paths and show an explicit capability limit for After return. Any supported exception/status mapping is shown separately as framework evidence; it is not a direct method call or proof of the live response.
Features
- A readable path beside your code. Numbered steps, simple arrows, wrapping names, light/dark themes, and a subtle highlight for your current location.
- Alternatives without clutter. Other callers stay collapsed until you need them. Explore an earlier step without losing the route.
- Separate App and Tests views. App is selected first. Test classification uses project hints and configurable patterns, with settings for each workspace folder.
- Source-backed evidence. Expand a relationship for available call sites and interface evidence. Path details shows full names, signatures, and workspace paths.
- A route that stays put. Editor navigation never replaces your route. Source changes visibly mark it stale until you refresh manually. Keyboard controls support Tab and Enter/Space; Left/Right switches App and Tests.
Requirements and language support
Requires VS Code 1.106 or newer, a trusted workspace, and a language provider that exposes document symbols and call hierarchy. Install and configure the normal language tooling for your project first.
| Language |
Verification |
| C# |
Real application routes, including possible interface implementations, using Microsoft C# and C# Dev Kit. |
| JavaScript |
Real callers in a separate repository using VS Code's built-in JavaScript/TypeScript provider. |
| TypeScript |
Alternatives, repeated names, recursion, long names, and saved-file changes in local test fixtures. |
| Other languages |
Capability-dependent. Other providers have not been verified; an installed language extension alone does not guarantee call hierarchy support. |
Verification used VS Code 1.139.1, Microsoft C# 2.160.4, C# Dev Kit 3.40.210, and .NET SDK 10.0.401 for the C# test repository. These are verified versions, not universal minimum requirements for every C# project. Local multi-root workspaces were tested; remote hosts were not.
How it works
Caller Path locates the containing function using document symbols, resolves it with vscode.prepareCallHierarchy, and traces callers with vscode.provideIncomingCalls. Symbols are identified by their source locations rather than by name alone. Traversal is bounded and checks for cycles.
For interface and base declarations, it can supplement direct results using semantic references, definitions, implementation locations, and call hierarchy. References find candidates; a reference alone is never treated as a verified call. A declaration-to-implementation link is labeled Possible implementation, with available evidence and alternatives. It does not prove which implementation dependency injection selects at runtime.
A static path is a possible calling route, not a recording of a live request. Caller Path does not guess missing edges or fall back to text-search caller matches.
Command
| Command |
Action |
| Show Caller Path |
Trace callers of the function containing your cursor. Available in the Command Palette and editor context menu. |
Settings
Find Caller Path in VS Code Settings, or use Settings inside the panel's Path details. Route settings can be configured per workspace folder; the executable path is a machine setting.
| Setting |
Default |
Purpose |
callerPath.dotnetPath |
Auto-discover |
Optional absolute .NET executable for C# After return; machine setting. |
callerPath.testGlobs |
Common test directories and test/spec filenames |
Identify test code. |
callerPath.appGlobs |
[] |
Treat matching paths as application code, overriding test hints. |
callerPath.excludeGlobs |
Common dependency, generated, and build paths |
Exclude paths from both views. |
callerPath.maxDepth |
12 |
Maximum functions per route; allowed range 2–30. |
callerPath.maxRoutes |
40 |
Maximum alternative routes; allowed range 1–100. |
callerPath.maxNodes |
120 |
Maximum symbols queried per analysis; allowed range 5–300. |
Patterns are relative to each workspace root, case-insensitive, and support **, *, ?, and simple {a,b} choices. Configured arrays replace their defaults. Exclusions take precedence over App and Tests patterns; empty arrays are supported. bin/ is not universally excluded because it can contain application source.
Test classification also uses unconditional .csproj test declarations and package.json directories.test. These are classification hints, not caller evidence. Unknown paths stay in App. App excludes identified test steps; Tests shows routes passing through identified tests. Adjust the patterns if your project uses another convention.
When tracing stops
- No provider or a loading project: the panel reports unavailable or incomplete results. Let the language server finish loading, then use Retry. The verified C# setup initially returned empty results during project loading.
- No further callers reported: this describes the provider's result, not proof that no caller exists. A timeout, exclusion, cycle, or traversal limit is reported separately.
- Framework or runtime boundaries: Caller paths do not infer HTTP routes, CLI registrations, middleware dispatch, events, reflection, or runtime dispatch. C# After return can separately show supported source-proven exception/status mapping evidence; it does not claim that the mapping handles this request. The path starts at the earliest source function established by the provider. Callbacks, generated code, outside-workspace code, and synthetic provider relationships can remain incomplete. Links without call sites are labeled.
- Interface evidence: discovery depends on provider support and checks up to 48 reference locations per function. Truncation is reported; every possible runtime implementation may not be discoverable.
- Changed source: edits, saves, and detected external changes mark the displayed route stale and disable its links. Save your edits and run Show Caller Path again to refresh. Configuration and workspace-folder changes also require manual refresh. Retry and App/Tests stay scoped to the original target. External detection watches source kinds already in the route; a manual command always clears cached analysis. Provider requests time out after 12 seconds each; cancelled or outdated results are discarded even if the provider continues working.
Privacy
Caller Path runs in the extension host and does not start your application. It has no telemetry, network requests, or AI integration. Ordinary caller paths use VS Code APIs; optional C# return analysis starts a bundled helper through the installed .NET SDK. It does not send source code to an external service. Your installed language providers have their own behavior and settings. Remote workspaces require the language provider on the workspace side; SSH and containers remain unverified.
Install from a local VSIX
Run Extensions: Install from VSIX…, select caller-path-0.3.1-marketplace.vsix, and reload if prompted. The extension ID is NizamulKazi.caller-path.
If you used an earlier development build published as local-tools, disable or uninstall that build first to avoid duplicate panels.
Development
The extension UI and caller engine are plain JavaScript. The optional C# return analyzer must be published before packaging. Packaging requires Node 22+; installed extensions use VS Code's bundled Node.
npm ci
npm run build:analyzer
dotnet restore test/return-analyzer-fixture/ReturnAnalyzerFixture.csproj
npm test
npm run check
npm run package
The real-repository analyzer probe also requires this checkout’s restored C# projects; the independent semantic fixture uses the restore command above.
In the source checkout, PROGRESS.md and artifacts/ record verification and actual UI screenshots. test/ contains focused behavioral tests, real-provider probes, and Extension Development Host checks. Test fixtures and local verification artifacts are excluded from the VSIX. Launch a host with --extensionDevelopmentPath=<extension-directory> and the workspace you want to explore.
API references: VS Code provider commands, call hierarchy, and Secondary Side Bar support.
License
MIT.