Move diagnostic generation from LibraryImportGenerator to LibraryImportDiagnosticsAnalyzer#123780
Conversation
… 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>
This comment was marked as resolved.
This comment was marked as resolved.
jkoritzinsky
left a comment
There was a problem hiding this comment.
@copilot address this review.
...ime.InteropServices/gen/LibraryImportGenerator/Analyzers/LibraryImportDiagnosticsAnalyzer.cs
Show resolved
Hide resolved
...ime.InteropServices/gen/LibraryImportGenerator/Analyzers/LibraryImportDiagnosticsAnalyzer.cs
Outdated
Show resolved
Hide resolved
...raries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/DiagnosticOr.cs
Outdated
Show resolved
Hide resolved
...aries/System.Runtime.InteropServices/tests/Common/Verifiers/CSharpSourceGeneratorVerifier.cs
Show resolved
Hide resolved
…per review feedback Co-authored-by: jkoritzinsky <1571408+jkoritzinsky@users.noreply.github.com>
...ibraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.cs
Outdated
Show resolved
Hide resolved
...braries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/Diagnostics.cs
Show resolved
Hide resolved
…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>
There was a problem hiding this comment.
Pull request overview
This pull request refactors diagnostic generation for LibraryImport by moving it from the LibraryImportGenerator source generator to a new LibraryImportDiagnosticsAnalyzer, following Roslyn team recommendations to separate diagnostic reporting from code generation.
Changes:
- Created
LibraryImportDiagnosticsAnalyzerthat runs diagnostic logic independently of the generator - Updated
LibraryImportGeneratorto filter invalid methods using the analyzer's validation logic instead of emitting diagnostics - Corrected
CompilationExtensions.GetEnvironmentFlagsto check forDisableRuntimeMarshallingAttributeon the assembly instead of the source module (aligning with the attribute'sAttributeTargets.Assemblyusage)
Reviewed changes
Copilot reviewed 21 out of 21 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
LibraryImportDiagnosticsAnalyzer.cs |
New analyzer that reports LibraryImport diagnostics independently from code generation |
LibraryImportGenerator.cs |
Removed diagnostic emission; now calls analyzer's validation method to filter methods |
Comparers.cs |
Removed Comparers static class wrapper (no longer needed without diagnostics in pipeline) |
CompilationExtensions.cs |
Fixed to check DisableRuntimeMarshallingAttribute on assembly (correct) vs module (incorrect) |
CSharpSourceGeneratorVerifier.cs |
Added TAnalyzer type parameter to support running both generator and analyzer in tests |
CSharpAnalyzerVerifier.cs |
Added constructor that disables compiler diagnostics and SYSLIB1092 by default |
Diagnostics.cs, CompileFails.cs, etc. |
Updated to use analyzer-only testing for diagnostic verification; removed compiler error expectations |
ByValueContentsMarshalling.cs |
Uses analyzer verifier with SYSLIB1092 re-enabled for specific tests |
| ComInterfaceGenerator test files | Updated type parameters to include analyzer types |
...ime.InteropServices/gen/LibraryImportGenerator/Analyzers/LibraryImportDiagnosticsAnalyzer.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Runtime.InteropServices/tests/Common/Verifiers/CSharpAnalyzerVerifier.cs
Show resolved
Hide resolved
...ime.InteropServices/gen/LibraryImportGenerator/Analyzers/LibraryImportDiagnosticsAnalyzer.cs
Outdated
Show resolved
Hide resolved
...stem.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/CompilationExtensions.cs
Show resolved
Hide resolved
🤖 Copilot Code Review — PR #123780Holistic AssessmentMotivation: Moving diagnostic generation from the Approach: The implementation correctly reuses the existing diagnostic infrastructure ( Summary: Detailed Findings
|
Co-authored-by: jkoritzinsky <1571408+jkoritzinsky@users.noreply.github.com>
|
/ba-g browser timeouts and Android failures unrelated. |
…rtDiagnosticsAnalyzer (dotnet#123780) ## Description Moves diagnostic generation/emit from the `LibraryImportGenerator` source generator to a new `LibraryImportDiagnosticsAnalyzer` in the same assembly, per Roslyn team recommendation. ### Changes Made #### 1. Created `LibraryImportDiagnosticsAnalyzer` - Runs the same diagnostic logic as the generator - Uses `SymbolEqualityComparer` to compare attribute types instead of string matching - Creates `LibraryImportGeneratorOptions` once per compilation in `RegisterCompilationStartAction` - `GetDiagnosticIfInvalidMethodForGeneration` is `internal static` so the generator can call it directly - Uses thread-safe access for `foundLibraryImportMethod` flag with `Interlocked.Exchange` and `Volatile.Read` #### 2. Updated `LibraryImportGenerator` - Removed diagnostic reporting from the pipeline - Calls `LibraryImportDiagnosticsAnalyzer.GetDiagnosticIfInvalidMethodForGeneration` directly to filter methods - No longer uses `DiagnosticOr` in the pipeline - Removed `Diagnostics` field from `IncrementalStubGenerationContext` - Inlined `Comparers.GeneratedSyntax` to use `SyntaxEquivalentComparer.Instance` directly - Removed the `Comparers` class static field wrapper #### 3. Updated `CompilationExtensions.GetEnvironmentFlags` - Changed to check for `DisableRuntimeMarshallingAttribute` on the source assembly instead of the module (aligning with the attribute's `AttributeTargets.Assembly` usage) #### 4. Updated Test Infrastructure - Added `TAnalyzer` type parameter to `CSharpSourceGeneratorVerifier` - Added `DisabledDiagnostics.Add(GeneratorDiagnostics.Ids.NotRecommendedGeneratedComInterfaceUsage)` to `CSharpAnalyzerVerifier` - Tests using `LibraryImportGenerator` use `LibraryImportDiagnosticsAnalyzer` - Tests using other generators use `EmptyDiagnosticAnalyzer` - `CSharpAnalyzerVerifier` uses targeted compiler diagnostic exclusion (CS8795, CS0751) instead of disabling all compiler diagnostics #### 5. Updated Test Files - `Diagnostics.cs`: Uses `CSharpAnalyzerVerifier` (analyzer-only testing) - `CompileFails.cs`: Uses `CSharpAnalyzerVerifier` for diagnostic tests - `ByValueContentsMarshalling.cs`: Uses analyzer verifier with SYSLIB1092 re-enabled for specific tests ### Test Results - **LibraryImportGenerator.Unit.Tests**: 702/703 pass (1 skipped) - **ComInterfaceGenerator.Unit.Tests**: 839/839 pass ### Key Architectural Decisions 1. **Analyzer runs independently**: The analyzer can run without the generator, making diagnostic-only tests faster 2. **Generator uses analyzer logic**: The generator calls the analyzer's `GetDiagnosticIfInvalidMethodForGeneration` method to share validation logic 3. **Test separation**: Tests that verify diagnostics run only the analyzer; tests that verify code generation run both 4. **Thread-safety**: The `foundLibraryImportMethod` flag uses `Interlocked`/`Volatile` for thread-safe access since `EnableConcurrentExecution()` is called 5. **Targeted diagnostic exclusion**: Analyzer-only tests exclude only CS8795 and CS0751 compiler diagnostics rather than all compiler diagnostics, ensuring typos in tests are still caught <!-- START COPILOT CODING AGENT TIPS --> --- ✨ Let Copilot coding agent [set things up for you](https://github.com/dotnet/runtime/issues/new?title=✨+Set+up+Copilot+instructions&body=Configure%20instructions%20for%20this%20repository%20as%20documented%20in%20%5BBest%20practices%20for%20Copilot%20coding%20agent%20in%20your%20repository%5D%28https://gh.io/copilot-coding-agent-tips%29%2E%0A%0A%3COnboard%20this%20repo%3E&assignees=copilot) — coding agent works faster and does higher quality work when set up for your repo. --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: jkoritzinsky <1571408+jkoritzinsky@users.noreply.github.com> Co-authored-by: Jeremy Koritzinsky <jkoritzinsky@gmail.com>
Description
Moves diagnostic generation/emit from the
LibraryImportGeneratorsource generator to a newLibraryImportDiagnosticsAnalyzerin the same assembly, per Roslyn team recommendation.Changes Made
1. Created
LibraryImportDiagnosticsAnalyzerSymbolEqualityComparerto compare attribute types instead of string matchingLibraryImportGeneratorOptionsonce per compilation inRegisterCompilationStartActionGetDiagnosticIfInvalidMethodForGenerationisinternal staticso the generator can call it directlyfoundLibraryImportMethodflag withInterlocked.ExchangeandVolatile.Read2. Updated
LibraryImportGeneratorLibraryImportDiagnosticsAnalyzer.GetDiagnosticIfInvalidMethodForGenerationdirectly to filter methodsDiagnosticOrin the pipelineDiagnosticsfield fromIncrementalStubGenerationContextComparers.GeneratedSyntaxto useSyntaxEquivalentComparer.InstancedirectlyComparersclass static field wrapper3. Updated
CompilationExtensions.GetEnvironmentFlagsDisableRuntimeMarshallingAttributeon the source assembly instead of the module (aligning with the attribute'sAttributeTargets.Assemblyusage)4. Updated Test Infrastructure
TAnalyzertype parameter toCSharpSourceGeneratorVerifierDisabledDiagnostics.Add(GeneratorDiagnostics.Ids.NotRecommendedGeneratedComInterfaceUsage)toCSharpAnalyzerVerifierLibraryImportGeneratoruseLibraryImportDiagnosticsAnalyzerEmptyDiagnosticAnalyzerCSharpAnalyzerVerifieruses targeted compiler diagnostic exclusion (CS8795, CS0751) instead of disabling all compiler diagnostics5. Updated Test Files
Diagnostics.cs: UsesCSharpAnalyzerVerifier(analyzer-only testing)CompileFails.cs: UsesCSharpAnalyzerVerifierfor diagnostic testsByValueContentsMarshalling.cs: Uses analyzer verifier with SYSLIB1092 re-enabled for specific testsTest Results
Key Architectural Decisions
GetDiagnosticIfInvalidMethodForGenerationmethod to share validation logicfoundLibraryImportMethodflag usesInterlocked/Volatilefor thread-safe access sinceEnableConcurrentExecution()is called✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.