Skip to content

Commit 6d98291

Browse files
authored
Enhance package analysis features and documentation (#2)
- Added deep dependency visualization with interactive, color-coded graphs to README.md and getting-started.md. - Implemented smart grouping of related packages and update recommendations in package analysis. - Updated PackageAnalyzerService to resolve and display transitive dependencies. - Introduced ASCII art representation of dependency graphs in the output. - Enhanced tests to validate transitive dependency collection and graph generation.
1 parent 6fe7c3e commit 6d98291

9 files changed

Lines changed: 384 additions & 7 deletions

File tree

README.md

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ NetContextServer empowers AI coding assistants like Cursor AI to deeply understa
2222
- 🛡️ **Built-in Security**: Safe file access with automatic protection of sensitive data
2323
- 🚀 **Cursor AI Integration**: Seamless setup with Cursor AI for enhanced coding assistance
2424
- 📦 **Package Analysis**: Understand your dependencies and get update recommendations
25+
- 🔍 **Deep Dependency Visualization**: See transitive dependencies with interactive, color-coded graphs
26+
- 🧩 **Smart Grouping**: Visually group related packages for easier navigation
27+
- 📊 **Update Recommendations**: Identify outdated packages and security issues
2528
-**Fast & Efficient**: Quick indexing and response times for large codebases
2629

2730
## 🚀 Quick Start
@@ -148,9 +151,34 @@ dotnet run --project src/NetContextClient/NetContextClient.csproj -- list-source
148151

149152
5. **Analyze Packages**:
150153
```bash
154+
# Set your base directory first
155+
dotnet run --project src/NetContextClient/NetContextClient.csproj -- set-base-dir --directory "path/to/your/project"
156+
157+
# Run the package analysis
151158
dotnet run --project src/NetContextClient/NetContextClient.csproj -- analyze-packages
152159
```
153160

161+
Example output:
162+
```
163+
Project: MyProject.csproj
164+
Found 2 package(s):
165+
- ✅ Newtonsoft.Json (13.0.1)
166+
Used in 5 location(s)
167+
168+
Dependencies:
169+
└─ Newtonsoft.Json
170+
└─ System.*
171+
└─ System.ComponentModel
172+
173+
- 🔄 Microsoft.Extensions.DependencyInjection (5.0.2 → 6.0.1)
174+
Update available: 6.0.1
175+
176+
Dependencies:
177+
└─ Microsoft.Extensions.DependencyInjection
178+
└─ Microsoft.*
179+
└─ Microsoft.Extensions.DependencyInjection.Abstractions
180+
```
181+
154182
### Search Commands
155183

156184
1. **Text Search**:
@@ -235,7 +263,12 @@ dotnet run --project src/NetContextClient/NetContextClient.csproj -- add-ignore-
235263
dotnet run --project src/NetContextClient/NetContextClient.csproj -- list-projects-in-dir --directory "D:\Projects\MyApp\src"
236264
```
237265

238-
4. Search for authentication-related code:
266+
4. Analyze your project's package dependencies:
267+
```bash
268+
dotnet run --project src/NetContextClient/NetContextClient.csproj -- analyze-packages
269+
```
270+
271+
5. Search for authentication-related code:
239272
```bash
240273
dotnet run --project src/NetContextClient/NetContextClient.csproj -- semantic-search --query "user authentication and authorization logic"
241274
```

docs/getting-started.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,22 @@ dotnet run --project src/NetContextClient/NetContextClient.csproj -- search-code
9797
dotnet run --project src/NetContextClient/NetContextClient.csproj -- semantic-search --query "how is user data validated"
9898
```
9999

100+
### Package Analysis
101+
```bash
102+
# First set your base directory
103+
dotnet run --project src/NetContextClient/NetContextClient.csproj -- set-base-dir --directory "path/to/your/project"
104+
105+
# Analyze packages across all projects
106+
dotnet run --project src/NetContextClient/NetContextClient.csproj -- analyze-packages
107+
```
108+
109+
The package analysis provides:
110+
- Visualization of transitive dependencies with color-coded graphs
111+
- Detection of unused packages (⚠️) and available updates (🔄)
112+
- Security vulnerability warnings (🔴)
113+
- Smart grouping of related packages by namespace
114+
- Recommendations for package maintenance
115+
100116
### Security Management
101117
```bash
102118
# Add files to ignore

docs/tool-reference.md

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,8 +136,48 @@ dotnet run --project src/NetContextClient/NetContextClient.csproj -- analyze-pac
136136

137137
**Output includes:**
138138
- Package versions and available updates
139-
- Usage analysis
139+
- Usage analysis and detection of unused packages
140+
- Security vulnerability warnings
140141
- Recommendations for updates or removal
142+
- Deep transitive dependency analysis
143+
- Visual dependency graph representation with smart grouping
144+
145+
**Dependency Graph Features:**
146+
- Hierarchical tree visualization in ASCII-art format
147+
- Automatic grouping of related dependencies by namespace
148+
- Color-coding of dependencies in the console:
149+
- Cyan: Leaf dependencies (end nodes)
150+
- Green: Intermediate dependencies
151+
- Yellow: Grouped namespaces
152+
- Clear visual separation between dependency groups
153+
- Configurable depth of transitive dependency resolution
154+
155+
**Example Output:**
156+
```
157+
Project: MyProject.csproj
158+
Found 3 package(s):
159+
- ✅ Newtonsoft.Json (13.0.1)
160+
Used in 5 location(s)
161+
162+
Dependencies:
163+
└─ Newtonsoft.Json
164+
├─ Microsoft.*
165+
│ └─ Microsoft.CSharp
166+
└─ System.*
167+
└─ System.ComponentModel
168+
169+
- 🔄 Microsoft.Extensions.DependencyInjection (5.0.2 → 6.0.1)
170+
Update available: 6.0.1
171+
Used in 3 location(s)
172+
173+
Dependencies:
174+
└─ Microsoft.Extensions.DependencyInjection
175+
└─ Microsoft.*
176+
└─ Microsoft.Extensions.DependencyInjection.Abstractions
177+
178+
- ⚠️ Unused.Package (1.0.0)
179+
Consider removing this unused package
180+
```
141181

142182
## Ignore Pattern Management
143183

src/NetContextClient/Models/PackageAnalysis.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,4 +49,9 @@ public class PackageAnalysis
4949
/// Gets or sets the list of packages that depend on this package.
5050
/// </summary>
5151
public List<string> TransitiveDependencies { get; set; } = [];
52+
53+
/// <summary>
54+
/// Gets or sets a visual representation of the dependency graph as ASCII art.
55+
/// </summary>
56+
public string? DependencyGraph { get; set; }
5257
}

src/NetContextClient/Program.cs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -651,6 +651,40 @@ static async Task<int> Main(string[] args)
651651
{
652652
await Console.Out.WriteLineAsync($" Used in {package.UsageLocations.Count} location(s)");
653653
}
654+
655+
// Display dependency graph if available
656+
if (!string.IsNullOrEmpty(package.DependencyGraph))
657+
{
658+
await Console.Out.WriteLineAsync("\n Dependencies:");
659+
var lines = package.DependencyGraph.Split(Environment.NewLine);
660+
foreach (var line in lines)
661+
{
662+
// Color code the dependency graph
663+
string coloredLine = line;
664+
if (line.Contains("└─"))
665+
{
666+
// Last items in their branch
667+
coloredLine = $"\u001b[36m{line}\u001b[0m"; // Cyan
668+
}
669+
else if (line.Contains("├─"))
670+
{
671+
// Middle items
672+
coloredLine = $"\u001b[32m{line}\u001b[0m"; // Green
673+
}
674+
else if (line.Contains(".*"))
675+
{
676+
// Group headers
677+
coloredLine = $"\u001b[33m{line}\u001b[0m"; // Yellow
678+
}
679+
680+
await Console.Out.WriteLineAsync($" {coloredLine}");
681+
}
682+
await Console.Out.WriteLineAsync();
683+
}
684+
else if (package.TransitiveDependencies.Count > 0)
685+
{
686+
await Console.Out.WriteLineAsync($" Has {package.TransitiveDependencies.Count} transitive dependencies");
687+
}
654688
}
655689

656690
await Console.Out.WriteLineAsync();

src/NetContextServer/Models/PackageAnalysis.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,4 +49,9 @@ public class PackageAnalysis
4949
/// Gets or sets the recommended action to take regarding this package (e.g., update, remove, etc.).
5050
/// </summary>
5151
public string? RecommendedAction { get; set; }
52+
53+
/// <summary>
54+
/// Gets or sets a visual representation of the dependency graph as ASCII art.
55+
/// </summary>
56+
public string? DependencyGraph { get; set; }
5257
}

src/NetContextServer/Services/PackageAnalyzerService.cs

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,49 @@ public async Task<PackageAnalysis> AnalyzePackageAsync(PackageReference package)
9393
analysis.LatestVersion = latestVersion.ToString();
9494
}
9595
}
96+
97+
// Resolve transitive dependencies
98+
try
99+
{
100+
var dependencyResource = await NuGetRepository.GetResourceAsync<DependencyInfoResource>();
101+
var packageDependencyInfo = await dependencyResource.ResolvePackage(
102+
new NuGet.Packaging.Core.PackageIdentity(package.Id, currentVersion),
103+
NuGet.Frameworks.NuGetFramework.ParseFolder("net6.0"),
104+
Cache,
105+
NullLogger.Instance,
106+
CancellationToken.None);
107+
108+
if (packageDependencyInfo != null)
109+
{
110+
var dependencies = new List<string>();
111+
var visited = new HashSet<string>();
112+
113+
// Start with the direct dependencies
114+
foreach (var dependency in packageDependencyInfo.Dependencies)
115+
{
116+
if (!visited.Contains(dependency.Id))
117+
{
118+
visited.Add(dependency.Id);
119+
dependencies.Add(dependency.Id);
120+
121+
// Recursively gather deeper dependencies
122+
await GatherDependenciesForPackageAsync(
123+
dependency.Id,
124+
dependency.VersionRange.MinVersion ?? NuGetVersion.Parse("0.0.1"),
125+
dependencies,
126+
visited,
127+
1,
128+
3);
129+
}
130+
}
131+
132+
analysis.TransitiveDependencies = dependencies;
133+
}
134+
}
135+
catch (Exception ex)
136+
{
137+
Console.WriteLine($"Error resolving dependencies for {package.Id}: {ex.Message}");
138+
}
96139

97140
// Check usage
98141
try
@@ -156,4 +199,46 @@ public async Task<PackageAnalysis> AnalyzePackageAsync(PackageReference package)
156199

157200
return analysis;
158201
}
202+
203+
private async Task GatherDependenciesForPackageAsync(string packageId, NuGetVersion packageVersion, List<string> dependencies, HashSet<string> visited, int currentDepth, int maxDepth)
204+
{
205+
if (currentDepth > maxDepth) return;
206+
if (visited.Contains(packageId)) return;
207+
visited.Add(packageId);
208+
209+
dependencies.Add(packageId);
210+
211+
try
212+
{
213+
var dependencyResource = await NuGetRepository.GetResourceAsync<DependencyInfoResource>();
214+
var dependencyInfo = await dependencyResource.ResolvePackage(
215+
new NuGet.Packaging.Core.PackageIdentity(packageId, packageVersion),
216+
NuGet.Frameworks.NuGetFramework.ParseFolder("net6.0"),
217+
Cache,
218+
NullLogger.Instance,
219+
CancellationToken.None);
220+
221+
if (dependencyInfo != null)
222+
{
223+
foreach (var childDependency in dependencyInfo.Dependencies)
224+
{
225+
if (!visited.Contains(childDependency.Id))
226+
{
227+
var minVersion = childDependency.VersionRange.MinVersion ?? NuGetVersion.Parse("0.0.1");
228+
await GatherDependenciesForPackageAsync(
229+
childDependency.Id,
230+
minVersion,
231+
dependencies,
232+
visited,
233+
currentDepth + 1,
234+
maxDepth);
235+
}
236+
}
237+
}
238+
}
239+
catch (Exception ex)
240+
{
241+
Console.WriteLine($"Error gathering dependencies for {packageId}: {ex.Message}");
242+
}
243+
}
159244
}

0 commit comments

Comments
 (0)