Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Jan 29, 2026

Description

Moves diagnostic generation from the LibraryImportGenerator source generator to a new LibraryImportDiagnosticsAnalyzer, per Roslyn team recommendation.

Changes:

  • Added LibraryImportDiagnosticsAnalyzer.cs with infrastructure to run diagnostic logic
    • Uses SymbolEqualityComparer to compare attribute types instead of string matching
    • Returns early when ProcessLibraryImportAttribute returns null (invalid compilation)
  • Updated CSharpSourceGeneratorVerifier to accept a TAnalyzer type parameter for specifying which analyzer to run alongside a generator
  • Removed diagnostic reporting from LibraryImportGenerator:
    • Removed all DiagnosticOr usage from the pipeline
    • Added IsValidMethodForGeneration method that returns a boolean for filtering
    • Methods are now filtered with Where directly before entering the pipeline
  • Updated diagnostic tests to use CSharpAnalyzerVerifier instead of CSharpSourceGeneratorVerifier:
    • Tests now run only the analyzer without the generator
    • Updated CSharpAnalyzerVerifier.Test to ignore compiler diagnostics since partial methods won't have implementations without the generator
  • Updated other test files to use two type parameters:
    • LibraryImportGenerator tests use LibraryImportDiagnosticsAnalyzer
    • Other generators use EmptyDiagnosticAnalyzer from Microsoft.CodeAnalysis.Testing as a placeholder

Current state: 672/703 tests pass (95%). The analyzer reports most diagnostics but doesn't yet handle all edge cases that the generator previously handled (e.g., InvalidStringMarshallingConfiguration validation, some MarshalAs field validations).

Next steps (future PRs):

  • Complete analyzer to handle all diagnostic edge cases
  • Apply pattern to ComInterfaceGenerator, JSImportGenerator, JSExportGenerator, DownlevelLibraryImportGenerator

✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI and others added 4 commits January 29, 2026 23:28
… diagnostics

Co-authored-by: jkoritzinsky <1571408+jkoritzinsky@users.noreply.github.com>
Co-authored-by: jkoritzinsky <1571408+jkoritzinsky@users.noreply.github.com>
…itional analyzer loading

Co-authored-by: jkoritzinsky <1571408+jkoritzinsky@users.noreply.github.com>
…till reports diagnostics)

Co-authored-by: jkoritzinsky <1571408+jkoritzinsky@users.noreply.github.com>
Copilot AI changed the title [WIP] Move diagnostic generation to analyzers alongside generators Add LibraryImportDiagnosticsAnalyzer foundation for diagnostic migration Jan 29, 2026
Copilot AI requested a review from jkoritzinsky January 29, 2026 23:53
jkoritzinsky

This comment was marked as outdated.

@jkoritzinsky jkoritzinsky dismissed their stale review January 30, 2026 00:15

Mis-clicked approve

@jkoritzinsky

This comment was marked as resolved.

Copy link
Member

@jkoritzinsky jkoritzinsky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot address this review.

Comment on lines 92 to 105

// Only analyze methods with LibraryImportAttribute
AttributeData? libraryImportAttr = null;
foreach (AttributeData attr in method.GetAttributes())
{
if (attr.AttributeClass?.ToDisplayString() == TypeNames.LibraryImportAttribute)
{
libraryImportAttr = attr;
break;
}
}

if (libraryImportAttr is null)
return false;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use the LibraryImportAttribute type from the compilation (via GetBestTypeByMetadataName) instead of matching on name

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 6232571. Now uses GetBestTypeByMetadataName to get the LibraryImportAttribute type and compares using SymbolEqualityComparer.Default.Equals.


// Process the LibraryImport attribute
LibraryImportCompilationData libraryImportData =
ProcessLibraryImportAttribute(libraryImportAttr) ??
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If ProcessLibraryImportAttribute returns null, we can stop handling diagnostics here. We already know we have an invalid compilation.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 6232571. Now returns early with empty diagnostics when ProcessLibraryImportAttribute returns null.

Comment on lines 113 to 122

/// <summary>
/// Filters the <see cref="IncrementalValuesProvider{TValue}"/> by whether or not the element has a value, discarding diagnostics.
/// Use this when diagnostics are reported by an analyzer instead of the generator.
/// </summary>
public static IncrementalValuesProvider<T> FilterWithoutReportingDiagnostics<T>(this IncrementalValuesProvider<DiagnosticOr<T>> diagnosticOrValues)
{
var (values, _) = diagnosticOrValues.Split();
return values;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll eventually remove usages of DiagnosticOr so we shouldn't need this helper anyway.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed in 6232571. Now uses Split() directly instead of a helper method.

Comment on lines 111 to 121
protected override IEnumerable<DiagnosticAnalyzer> GetDiagnosticAnalyzers()
{
// Include the corresponding diagnostics analyzer when testing specific generators.
// Note: The analyzer is available alongside the generator but diagnostics are still
// reported by the generator for now. This will change as we migrate diagnostics to analyzers.
foreach (var analyzer in base.GetDiagnosticAnalyzers())
{
yield return analyzer;
}
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of overriding GetDiagnosticAnalyzers(), update CSharpSourceGeneratorVerifier to have a TAnalyzer argument as well (and instantiate an instance of that analyzer here).

That should enable you to remove the diagnostics from the LibraryImportGenerator source generator's code.

…per review feedback

Co-authored-by: jkoritzinsky <1571408+jkoritzinsky@users.noreply.github.com>
Copilot AI changed the title Add LibraryImportDiagnosticsAnalyzer foundation for diagnostic migration Move diagnostic generation from LibraryImportGenerator to LibraryImportDiagnosticsAnalyzer Jan 30, 2026
Copilot AI requested a review from jkoritzinsky January 30, 2026 00:47
});

var methodsToGenerate = context.FilterAndReportDiagnostics(methodsWithDiagnostics);
// Filter methods but don't report diagnostics - the analyzer will handle that
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot Filter out the diagnostics earlier. I would like to not see DiagnosticOr used in the pipeline at all and instead have diagnostics dropped before they ever get into a step's output.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 7a1d4df. Removed DiagnosticOr from the pipeline entirely. Methods are now filtered with Where directly using a new IsValidMethodForGeneration method that returns a boolean.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot since we're moving the diagnostics to be emitted by the analyzer, we can change these tests to not run the generator and only run the analyzer.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 7a1d4df. Changed Diagnostics.cs to use CSharpAnalyzerVerifier<LibraryImportDiagnosticsAnalyzer> instead of running the generator. Updated the analyzer verifier to ignore compiler diagnostics since without the generator, partial methods don't have implementations.

…null, remove helper method

Co-authored-by: jkoritzinsky <1571408+jkoritzinsky@users.noreply.github.com>
…analyzer only

Co-authored-by: jkoritzinsky <1571408+jkoritzinsky@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

2 participants