C# Dependency Graph
Generate interactive dependency graphs for C# projects and classes directly from Visual Studio Code.
Recent Changes
- Enhanced Package Optimization: Fixed duplicate files in the VSIX package, significantly reducing its size
- Improved Resource Loading: Added robust resource loading that works in both development and production environments
- Fixed Webview Initialization: Resolved "Required script URIs are not defined" error in the Graphviz preview
- Added New NPM Scripts: Simplified packaging process with optimized scripts for building and packaging
- SVG Export Enhancement: Improved SVG export functionality from the graph preview
- Cycle Detection Improvements: Enhanced cycle detection algorithm for better performance and accuracy
Change Log
See CHANGELOG.md for a list of changes in README.md
Features
- Project-level dependency visualization: See how your C# projects depend on each other
- Class-level dependency analysis: Analyze dependencies between classes across your solution
- Solution file support: Automatically detect and use .sln files to find all projects in a solution structure
- Customizable output: Configure which elements to include in your dependency graph
- Exclude test projects: Option to exclude test projects from the analysis
- DOT file output: Generate standard DOT files for use with internal preview feature or other visualization tools like Graphviz
- Preview Graphviz: Preview Graphviz on graphviz file open (beta)
- Highlight dependencies: Highlight dependencies in the preview graph (beta)
- Customizable colors: Customize the colors of classes and packages in the graph
- Preview configuration options: Preview configuration options in settings
- Export graph as SVG: Export the generated graph as an SVG file for easy sharing and embedding
- Cycle detection: Detect cycles in project and class dependencies
- Cycle report generation: Generate a report of cycles in dependencies
- Cycle analysis: Analyze hotspots and breakpoints in cycles
Screenshots
Project Dependencies

Select view->Command Palette: C#: Generate Dependency Graph
and select Project Dependencies
Graph is generated in the selected folder. You can open it in Graphviz, Graphviz Online or Graphviz Preview
Class Dependencies
Select view->Command Palette: C#: Generate Dependency Graph
and select Class Dependencies
Graph is generated in the selected folder. You can open it in Graphviz, Graphviz Online or Graphviz Preview

Installation
From VS Code Marketplace
- Open VS Code
- Go to Extensions (Ctrl+Shift+X)
- Search for "C# Dependency Graph"
- Click Install
Manual Installation
- Download the .vsix file from the releases page
- In VS Code, go to Extensions (Ctrl+Shift+X)
- Click on the "..." menu (top-right) and select "Install from VSIX..."
- Select the downloaded .vsix file
Requirements
- Visual Studio Code 1.75.0 or higher
- A C# project (typically a .NET solution with .csproj files)
Usage
Generating a Dependency Graph
- Open a folder containing C# projects in VS Code
- Press
Ctrl+Shift+P
to open the command palette
- Type "C#: Generate Dependency Graph" and select the command
- If solution (.sln) files are found, you'll be asked if you want to use one of them
- Choose the type of dependency graph:
- Project Dependencies: Shows relationships between projects
- Class Dependencies: Shows detailed relationships between classes
- Select where to save the .dot file
- The graph will be generated and saved to the specified location
Viewing the Graph

You can view the generated .dot file using:
Example Class Dependency Graph
Here's an example of a class dependency graph generated by the extension:

Detailed Usage Examples
Example 1: Generating a Project Dependency Graph
- Open a folder containing multiple C# projects in VS Code.
- Press
Ctrl+Shift+P
to open the command palette.
- Type "C#: Generate Dependency Graph" and select the command.
- If solution (.sln) files are found, you'll be asked if you want to use one of them. Select a solution file or choose to scan for all projects.
- Choose "Project Dependencies" when prompted for the type of dependency graph.
- Select a location to save the .dot file.
- The graph will be generated and saved to the specified location. You can open it using Graphviz or the Graphviz Preview extension.
Example 2: Generating a Class Dependency Graph
- Open a folder containing a C# project in VS Code.
- Press
Ctrl+Shift+P
to open the command palette.
- Type "C#: Generate Dependency Graph" and select the command.
- If solution (.sln) files are found, you'll be asked if you want to use one of them. Select a solution file or choose to scan for all projects.
- Choose "Class Dependencies" when prompted for the type of dependency graph.
- Select a location to save the .dot file.
- The graph will be generated and saved to the specified location. You can open it using Graphviz or the Graphviz Preview extension.
Extension Settings
This extension contributes the following settings:
csharpDependencyGraph.useSolutionFile
: Enable or disable using .sln files to identify projects (default: true)
csharpDependencyGraph.includeNetVersion
: Include .NET framework version in project nodes (default: true)
csharpDependencyGraph.includePackageDependenciesInProjectGraph
: Include NuGet package dependencies in the project dependency graph (default: false)
csharpDependencyGraph.classDependencyColor
: Color for the classes in class dependency graph (default: lightgray)
csharpDependencyGraph.packageDependencyColor
: Color for the packages in project dependency graph (default: #ffcccc)
csharpDependencyGraph.excludeTestProjects
: Exclude test projects from the dependency graph (default: true)
csharpDependencyGraph.testProjectPatterns
: Glob patterns to identify test projects
csharpDependencyGraph.excludeSourcePatterns
: Glob patterns for source files to exclude from analysis
csharpDependencyGraph.openPreviewOnGraphvizFileOpen
: Enable or disable previewing Graphviz on graphviz file open (default: true)

How It Works
The extension works by:
- Finding and parsing .sln files (if enabled) or searching for all .csproj files in the workspace
- Parsing the project files to extract project references
- For class-level analysis, parsing all C# files to extract class dependencies including:
- Inheritance relationships
- Field and property types
- Method parameter and return types
- Static method calls
- Object instantiations
- Generating a DOT file representation of the dependency graph
- Analyzing cycles in dependencies
- Generating a report of cycles in dependencies
Code organization
classDiagram
direction LR
class Extension {
+activate(context: vscode.ExtensionContext)
}
%% Strategy Pattern classes
class GraphGenerationStrategy {
<<interface>>
+generate(projects: Project[], options: GraphOptions, additionalData?: StrategyAdditionalData): string
}
class BaseGraphStrategy {
<<abstract>>
+generate(projects: Project[], options: GraphOptions, additionalData?: StrategyAdditionalData): string
#generateHeader(): string
#generateFooter(): string
}
class ProjectGraphStrategy {
+generate(projects: Project[], options: GraphOptions, _additionalData?: StrategyAdditionalData): string
-generateProjectNodes(projects, options): string
-generatePackageNodes(projects, options): string
-collectUniquePackages(projects): Set~string~
-generateProjectEdges(projects): string
-generatePackageEdges(projects): string
}
class ClassGraphStrategy {
+generate(projects: Project[], options: GraphOptions, additionalData?: StrategyAdditionalData): string
-generateProjectSubgraphs(projects, classDependencies, options): string
-generateClassDependencyEdges(classDependencies): string
-findTargetClass(classDependencies, sourceClass, dependency): ClassDependency
}
class GraphGenerator {
-projectGraphStrategy: ProjectGraphStrategy
-classGraphStrategy: ClassGraphStrategy
+constructor()
+generateDotFile(projects: Project[], options: GraphOptions, classDependencies?: ClassDependency[]): string
}
%% Original classes for other functionality
class CsprojFinder {
+findCsprojFiles(workspaceFolder: string, excludeTestProjects: boolean, testProjectPatterns: string[], useSolutionFile: boolean): Promise<string[]>
}
class CsprojParser {
+parseCsprojFiles(csprojPaths: string[]): Promise<Project[]>
}
class SlnParser {
+findSolutionFiles(directoryPath: string): Promise<string[]>
+parseSolutionFile(slnFilePath: string): Promise<string[]>
}
class CsharpSourceFinder {
+findCSharpSourceFiles(workspaceFolder: string, excludeSourcePatterns: string[]): Promise<string[]>
}
class CsharpClassParser {
+parseClassDependencies(sourceFiles: string[]): Promise<ClassDependency[]>
}
class GraphPreviewProvider {
-_panel: vscode.WebviewPanel | undefined
-_extensionUri: vscode.Uri
-_sourceFilePath: string | undefined
-_dotContent: string
-_cyclesOnlyDotContent: string | undefined
-_hasCycles: boolean
+constructor(extensionUri: vscode.Uri)
+showPreview(dotContent: string, title: string, sourceFilePath?: string, cyclesOnlyDotContent?: string): void
-_handleExistingPanel(title: string, dotContent: string): void
-_createNewPanel(title: string, dotContent: string): void
-_getWebviewOptions(): vscode.WebviewOptions & vscode.WebviewPanelOptions
-_handleWebviewMessage(message: WebviewMessageType): Promise<void>
-_handleExportSvg(message: ExportSvgMessage): Promise<void>
-_getDefaultExportUri(title?: string): vscode.Uri
-_updateContent(dotContent: string): void
-_prepareTemplateParams(dotContent: string): GraphPreviewTemplateParams
}
class VizInitializer {
+prepareVizJs(extensionUri: vscode.Uri): Promise<boolean>
}
class CycleUtils {
-static readonly cycleCache: Map~string, string[][]~
-static generateCacheKey(graph: Map~string, string[]~): string
+static getCachedCycles(graph: Map~string, string[]~): string[][] | undefined
+static storeCycles(graph: Map~string, string[]~, cycles: string[][]): void
+static removeDuplicateCycles(cycles: string[][]): string[][]
+static isCycleAlreadyDetected(cycle: string[], existingCycles: string[][]): boolean
-static normalizeCycle(cycle: string[]): string[]
}
class CycleDetector {
+detectProjectCycles(projects: Project[]): CycleAnalysisResult
+detectClassCycles(classes: ClassDependency[]): CycleAnalysisResult
+generateDotWithHighlightedCycles(dotContent: string, cycles: Cycle[]): string
+generateCyclesOnlyGraph(cycles: Cycle[]): string
+generateCycleReport(cycles: Cycle[]): string
}
%% Cycle detection helper functions
class CycleDetectionHelpers {
<<utility>>
+findAllCycles(graph: Map~string, string[]~): string[][]
+findCyclesFromNode(startNode: string, graph: Map~string, string[]~, visited: Set~string~, cycles: string[][]): void
+handleBacktracking(stack: Array~object~): void
+handleCycleDetection(path: string[], cycleEndNode: string, cycles: string[][]): void
+exploreNeighbor(neighbor: string, graph: Map~string, string[]~, stack: Array~object~): void
+analyzeHotspotsAndBreakpoints(cycles: Cycle[]): object
}
class DotSanitizer {
+sanitizeDotContent(dotContent: string): DotSanitizeResult
+enhanceGraphWithDefaultAttributes(content: string): string
+isValidDotGraph(content: string): boolean
+sanitizeStringValue(value: string): string
}
class DotParser {
+static extractNodes(dotContent: string): Set~string~
+static extractEdges(dotContent: string): Map~string, string[]~
+static extractNodesFromEdges(dotContent: string): Set~string~
+static isClassDependencyGraph(dotContent: string): boolean
+static parse(dotContent: string): object
}
%% Strategy Pattern relationships
GraphGenerationStrategy <|.. BaseGraphStrategy : implements
BaseGraphStrategy <|-- ProjectGraphStrategy : extends
BaseGraphStrategy <|-- ClassGraphStrategy : extends
GraphGenerator o-- ProjectGraphStrategy : uses
GraphGenerator o-- ClassGraphStrategy : uses
%% Legacy adapter relationships
Extension --> GraphGenerator : uses adapter
%% Other relationships
Extension --> CsprojFinder
Extension --> CsprojParser
Extension --> CycleDetector
Extension --> CsharpSourceFinder
Extension --> CsharpClassParser
Extension --> SlnParser
Extension --> GraphPreviewProvider
Extension --> VizInitializer
Extension --> DotSanitizer
Extension --> DotParser : uses
CsprojFinder --> SlnParser
GraphPreviewProvider ..> VizInitializer : uses
GraphPreviewProvider ..> DotSanitizer : uses
Extension ..> DotSanitizer : uses
CycleDetector ..> CycleUtils : uses
CycleDetector ..> CycleDetectionHelpers : uses
CycleDetectionHelpers ..> CycleUtils : uses
Known Issues
- Very large codebases with many classes may generate complex graphs that are difficult to render
- Some complex C# syntax constructs might not be correctly parsed for class dependencies
- The extension currently only analyzes direct project references in .csproj files, not transitive package references
Troubleshooting Tips
Issue: Graph is not rendering correctly
- Solution: Ensure that the .dot file is correctly formatted. You can use online tools like Graphviz Online to validate the DOT file.
Issue: No .csproj files found
- Solution: Make sure that your workspace contains .csproj files. If you are using a solution file, ensure that it references the correct projects.
Issue: Class dependencies are not detected
- Solution: Ensure that the source files are not excluded by the
excludeSourcePatterns
setting. Also, make sure that the C# files are correctly parsed and contain valid class definitions.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Development Guide
Prerequisites
Setting Up the Development Environment
Clone the repository:
git clone https://github.com/magic5644/vscode-csharp-dependency-graph.git
cd vscode-csharp-dependency-graph
Install dependencies:
npm install
Building the Extension
To build the extension, run:
npm run compile
For continuous compilation during development:
npm run watch
Running the Extension
Open the project in Visual Studio Code:
code .
Press F5
to start debugging. This will launch a new VS Code window with the extension loaded.
In the new window, open a folder containing C# projects to test the extension.
Running Tests
To compile and run the tests:
npm run test-compile
npm test
Packaging the Extension
To create a VSIX package that can be installed in VS Code:
npm run package:vsix
This command performs a clean build and then packages the extension, ensuring the VSIX file is optimized without duplicate files. The output VSIX file will be created in the root directory of the project.
If you want to check the contents of the VSIX package before distribution, you can run:
npx vsce ls --tree vscode-csharp-dependency-graph-*.vsix
This will display the file structure inside the package, helping you verify that no unnecessary or duplicate files are included.
Debugging Common Issues
Webview Loading Issues
If you encounter issues with the webview not loading correctly (e.g., "Required script URIs are not defined" error), check that:
- The script URIs are correctly passed to the webview
- The required JavaScript files exist in the correct location
- The extension can locate resources in both development and production modes
Resource Path Issues
The extension is designed to work with resources in both development mode (resources/
folder) and production mode (dist/resources/
folder). If you encounter issues with missing resources:
- Check the console logs for resource verification results
- Ensure the build process correctly copies resources to the
dist/
folder
- Verify the resource loading logic in
graphPreview.ts
Coding Guidelines
- Follow the TypeScript style guide
- Write clear and concise code comments
- Include unit tests for new functionality
- Update the README.md if you add new features or settings
- Ensure resources work in both development and production environments
Submitting a Pull Request
- Create a new branch for your changes
- Make your changes and commit them
- Push your branch to GitHub
- Create a Pull Request against the main branch
- Ensure all tests pass
- Wait for review and address any feedback
License
This extension is licensed under the MIT License.