Skip to main content
The NuGetDiagnosticProvider class creates inline error and warning diagnostics in project files for NuGet package compatibility issues.

Class Overview

Location: /workspace/source/src/nugetDiagnosticProvider.ts:22
export class NuGetDiagnosticProvider {
    private diagnosticCollection: vscode.DiagnosticCollection;
    private workspaceRoot: string;

    constructor();
    public async updateDiagnostics(
        projectFile: string,
        issues: EnhancedCompatibilityIssue[]
    ): Promise<void>;
    public clearDiagnostics(): void;
    public dispose(): void;
}

Constructor

new NuGetDiagnosticProvider()

Creates a new diagnostic provider instance.
constructor()
Initialization:
  • Creates a diagnostic collection with ID 'dotnetBuildBuddy'
  • Stores workspace root path for file operations
Example:
import { NuGetDiagnosticProvider } from './nugetDiagnosticProvider';

const diagnosticProvider = new NuGetDiagnosticProvider();
The diagnostic collection is registered with VS Code and appears in the Problems panel.

Public Methods

updateDiagnostics

Updates inline diagnostics for a project file based on compatibility issues.
public async updateDiagnostics(
    projectFile: string,
    issues: EnhancedCompatibilityIssue[]
): Promise<void>
projectFile
string
required
Absolute path to the project file (.csproj, .fsproj, or .vbproj)
issues
EnhancedCompatibilityIssue[]
required
Array of compatibility issues to display as diagnostics
interface EnhancedCompatibilityIssue extends CompatibilityIssue {
    suggestedVersion?: string;
    alternativePackage?: {
        name: string;
        version?: string;
        reason?: string;
    };
    transitiveIssues?: Array<{
        packageName: string;
        version?: string;
        message: string;
    }>;
}
Behavior:
  1. Opens the project file as a VS Code document
  2. Parses the file content to locate PackageReference elements
  3. Creates diagnostics at the exact location of problematic packages
  4. Adds the diagnostics to VS Code’s Problems panel
  5. Displays inline warnings/errors in the editor
Example Usage:
import { NuGetDiagnosticProvider } from './nugetDiagnosticProvider';
import { NuGetCompatibilityChecker } from './nugetCompatibilityChecker';

const diagnosticProvider = new NuGetDiagnosticProvider();
const checker = new NuGetCompatibilityChecker();

const projectFile = '/workspace/MyProject/MyProject.csproj';
const packageRefs = [
    { Include: 'System.Web.Mvc', Version: '5.2.7' }
];

const issues = await checker.checkProjectCompatibilityEnhanced(
    packageRefs,
    'net8.0'
);

await diagnosticProvider.updateDiagnostics(projectFile, issues);
Result in Problems Panel:
ERROR [MyProject.csproj:12] Package System.Web.Mvc is not compatible with net8.0

💡 Alternative package: Microsoft.AspNetCore.Mvc (8.0.0) - Modern ASP.NET Core MVC for .NET Core/.NET 5+

📝 This package supports: net40, net45, ..., net48

clearDiagnostics

Clears all diagnostics from the Problems panel.
public clearDiagnostics(): void
Example Usage:
diagnosticProvider.clearDiagnostics();
Use this when re-checking compatibility or when diagnostics are no longer relevant.

dispose

Disposes the diagnostic collection and cleans up resources.
public dispose(): void
Example Usage:
diagnosticProvider.dispose();
Always call dispose() when the diagnostic provider is no longer needed to prevent resource leaks.

Diagnostic Details

Severity Levels

Diagnostics are created with different severity levels based on the issue type:
incompatible
Error
Red squiggly line - Package is incompatible with target framework
version_mismatch
Warning
Yellow squiggly line - Package version is incorrect or outdated
deprecated
Warning
Yellow squiggly line - Package or version is deprecated

Diagnostic Location

Diagnostics are positioned at the Include attribute of the PackageReference:
<PackageReference Include="System.Web.Mvc" Version="5.2.7" />
                  ^^^^^^^^^^^^^^^^^^^^^^^^^
                  Diagnostic appears here
Line Matching Algorithm:
  1. Searches file content for PackageReference with matching package name
  2. Calculates line number from file position
  3. Locates the Include attribute on that line
  4. Creates a range covering the attribute value

Diagnostic Messages

Messages include all available information from the compatibility issue:

Basic Message

Package System.Web.Mvc is not compatible with net8.0

With Suggested Version

Package Microsoft.EntityFrameworkCore version 6.0.0 is too old for net8.0

💡 Suggested version: 8.0.0

With Alternative Package

Package EntityFramework is not compatible with net8.0

🔄 Alternative package: Microsoft.EntityFrameworkCore (8.0.0)
   Modern Entity Framework Core for .NET Core/.NET 5+

With Recommendation

Package Newtonsoft.Json version 10.0.0 is too old

📝 Upgrade to at least version 11.0.0

With Transitive Issues

Package SomePackage has compatibility issues

⚠️ Transitive dependency issues:
  • Microsoft.AspNetCore.Mvc 2.0.0: Package version is too old for net8.0
  • System.Text.Json 4.0.0: Package is not compatible with net8.0

Integration with DotNetProjectManager

The diagnostic provider is automatically used by DotNetProjectManager when checking compatibility:
private async checkAllProjectCompatibility(): Promise<void> {
    const projectFiles = await this.findProjectFiles();
    
    for (const projectFile of projectFiles) {
        const projectInfo = await this.readProjectFile(projectFile);
        const targetFramework = projectInfo.targetFramework || 'net8.0';

        if (projectInfo.packageReferences) {
            const compatibilityIssues = 
                await this.compatibilityChecker.checkProjectCompatibilityEnhanced(
                    projectInfo.packageReferences,
                    targetFramework
                );

            // Update inline diagnostics
            await this.diagnosticProvider.updateDiagnostics(
                projectFile,
                compatibilityIssues
            );
        }
    }
}

Visual Representation

In Editor

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <!-- Error: Red squiggly line -->
    <PackageReference Include="System.Web.Mvc" Version="5.2.7" />
    
    <!-- Warning: Yellow squiggly line -->
    <PackageReference Include="Newtonsoft.Json" Version="10.0.0" />
    
    <!-- No issue: No decoration -->
    <PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.0" />
  </ItemGroup>
</Project>

In Problems Panel

Problems (2)
├─ MyProject.csproj
│  ├─ ❌ [Ln 8, Col 5] Package System.Web.Mvc is not compatible with net8.0
│  │   💡 Alternative package: Microsoft.AspNetCore.Mvc
│  └─ ⚠️ [Ln 11, Col 5] Package Newtonsoft.Json version 10.0.0 is too old
│      📝 Upgrade to at least version 11.0.0

Code Actions (Quick Fixes)

The diagnostic provider adds related information that can be used for code actions:
if (issue.suggestedVersion) {
    diagnostic.relatedInformation = [
        new vscode.DiagnosticRelatedInformation(
            new vscode.Location(document.uri, range),
            `Quick fix: Update to version ${issue.suggestedVersion}`
        )
    ];
}
Future enhancement: Implement code action provider to automatically update package versions when user clicks “Quick Fix”.

Error Handling

File Not Found

If the project file doesn’t exist, the method returns early without creating diagnostics:
if (!fs.existsSync(projectFile)) {
    return;
}

Package Not Found in File

If a PackageReference cannot be located in the file (e.g., conditionally included), no diagnostic is created for that package:
if (position === -1) {
    return null; // Skip this diagnostic
}

Malformed XML

The provider handles regex matching failures gracefully and skips diagnostics that can’t be positioned correctly.

Usage Example

Complete Integration

import * as vscode from 'vscode';
import { NuGetCompatibilityChecker } from './nugetCompatibilityChecker';
import { NuGetDiagnosticProvider } from './nugetDiagnosticProvider';

class ProjectValidator {
    private checker: NuGetCompatibilityChecker;
    private diagnosticProvider: NuGetDiagnosticProvider;

    constructor() {
        this.checker = new NuGetCompatibilityChecker();
        this.diagnosticProvider = new NuGetDiagnosticProvider();
    }

    async validateProject(projectFile: string, targetFramework: string) {
        // Read project file and extract package references
        const packageRefs = await this.getPackageReferences(projectFile);
        
        // Check compatibility
        const issues = await this.checker.checkProjectCompatibilityEnhanced(
            packageRefs,
            targetFramework
        );
        
        // Update diagnostics in editor
        await this.diagnosticProvider.updateDiagnostics(projectFile, issues);
        
        // Also report to user
        if (issues.length > 0) {
            vscode.window.showWarningMessage(
                `Found ${issues.length} compatibility issue(s). Check the Problems panel.`
            );
        }
    }

    clearAll() {
        this.diagnosticProvider.clearDiagnostics();
    }

    dispose() {
        this.diagnosticProvider.dispose();
    }
}

Extension Lifecycle

let diagnosticProvider: NuGetDiagnosticProvider;

export function activate(context: vscode.ExtensionContext) {
    diagnosticProvider = new NuGetDiagnosticProvider();
    
    // Register for cleanup
    context.subscriptions.push({
        dispose: () => diagnosticProvider.dispose()
    });
}

export function deactivate() {
    if (diagnosticProvider) {
        diagnosticProvider.dispose();
    }
}

Performance Considerations

Best Practices:
  • Call updateDiagnostics only when package references change
  • Use clearDiagnostics before updating to avoid stale entries
  • Dispose the provider when no longer needed
  • Batch multiple project updates together
Memory Usage:
  • One diagnostic collection per provider instance
  • Diagnostics are stored per file URI
  • Old diagnostics are automatically replaced
CPU Usage:
  • File parsing uses efficient regex matching
  • Diagnostic creation is fast and synchronous
  • No heavy computation involved
Creating too many diagnostic providers can lead to duplicate entries in the Problems panel. Use a single provider instance per extension.

Build docs developers (and LLMs) love