Always generate aliased usings#12
Merged
Merged
Conversation
…er` (with semantic-model requalification)) completed
…er (always-aliased, no duplication)) completed
…er (always-aliased, no duplication)) completed
…ider` for both providers) completed
There was a problem hiding this comment.
Pull request overview
This PR updates the SourceGenerator’s image-handler code fixes to always generate aliased image usings (and always qualify PreImage/PostImage parameter types with that alias), eliminating ambiguity when multiple image-registration namespaces are imported in the same file. It also introduces a custom FixAll provider to apply multiple image-handler fixes in a single consolidated rewrite pass.
Changes:
- Always emit aliased image usings and alias-qualified image parameter types in both handler signature fixes and handler method creation fixes.
- Rework image-using rewrite logic to support multiple namespaces and (when available) use a semantic model to correctly re-qualify existing bare
PreImage/PostImagereferences. - Add
AliasedImageUsingsFixAllProviderand expand tests to cover FixAll and multi-registration scenarios.
Reviewed changes
Copilot reviewed 8 out of 9 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| XrmPluginCore.SourceGenerator/Helpers/SyntaxFactoryHelper.cs | Adds “always alias” APIs and semantic-model-backed rewrite logic for qualifying image references. |
| XrmPluginCore.SourceGenerator/Helpers/RegisterStepHelper.cs | Adds helper to resolve the RegisterStep service type from a diagnostic span (used by FixAll). |
| XrmPluginCore.SourceGenerator/CodeFixes/FixHandlerSignatureCodeFixProvider.cs | Switches to always alias image params/usings; uses the new FixAll provider. |
| XrmPluginCore.SourceGenerator/CodeFixes/CreateHandlerMethodCodeFixProvider.cs | Switches to always alias method params/usings; uses the new FixAll provider. |
| XrmPluginCore.SourceGenerator/CodeFixes/AliasedImageUsingsFixAllProvider.cs | New consolidated FixAll provider for image-handler code fixes. |
| XrmPluginCore.SourceGenerator.Tests/DiagnosticTests/FixHandlerSignatureCodeFixProviderTests.cs | Updates assertions for alias-qualified output; adds multi-using + FixAll coverage. |
| XrmPluginCore.SourceGenerator.Tests/DiagnosticTests/CreateHandlerMethodCodeFixProviderTests.cs | Updates assertions for alias-qualified output; adds FixAll coverage. |
| XrmPluginCore.SourceGenerator.Tests/DiagnosticTests/CodeFixTestBase.cs | Adds test helper to exercise a provider’s FixAll path. |
| .gitignore | Ignores .conducktor/ local files. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…ixAll title) - SyntaxFactoryHelper: only treat a plain (non-aliased) using as "already present" for the image namespace. A namespace imported under a different alias no longer suppresses the standard alias, which the emitted parameter types reference. - CreateHandlerMethodCodeFixProvider: track the target interface with a SyntaxAnnotation (binding via a ReplaceSyntaxTree'd semantic model) instead of re-finding by identifier text, so same-named interfaces across namespaces or nested types resolve correctly. - AliasedImageUsingsFixAllProvider: use a descriptive constant title for the FixAll code action; keep the equivalence key for identity only. - Add regression tests for both behavioral fixes (verified failing without the fix); full suite 80/80. Co-Authored-By: Claude <noreply@anthropic.com> via Conducktor <conducktor@contextand.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Always generate aliased usings for plugin image registrations
Context
The
XrmPluginCore.SourceGeneratorships analyzers + code-fix providers that wire up type-safe Pre/Post image handler signatures. When aRegisterStep<TEntity, TService>(...)registration declares an image viaWithPreImage/WithPostImage/AddImagebut the referenced handler method's signature does not match, two diagnostics/code-fixes come into play:FixHandlerSignatureCodeFixProvider(XrmPluginCore.SourceGenerator/CodeFixes/FixHandlerSignatureCodeFixProvider.cs) — fixes an existing handler method's parameter list to accept the registeredPreImage/PostImagewrapper types. Fires onDiagnosticDescriptors.HandlerSignatureMismatch.IdandDiagnosticDescriptors.HandlerSignatureMismatchError.Id.CreateHandlerMethodCodeFixProvider(XrmPluginCore.SourceGenerator/CodeFixes/CreateHandlerMethodCodeFixProvider.cs) — creates a missing handler method on the service interface with the correct image parameters. Fires onDiagnosticDescriptors.HandlerMethodNotFound.Id.Each registration's image wrapper classes (
PreImage,PostImage) are generated into an isolated namespace produced byRegisterStepHelper.GetExpectedImageNamespace(...)(XrmPluginCore.SourceGenerator/Helpers/RegisterStepHelper.cs:17), with the shape:e.g.
Some.Namespace.Plugins.PluginRegistrations.SomePlugin.LeadUpdatePostOperation. The shared marker for these namespaces is the substring.PluginRegistrations.(SyntaxFactoryHelper.IsImageRegistrationNamespace,SyntaxFactoryHelper.cs:207). The alias used is the last namespace segment (GetLastNamespaceSegment,SyntaxFactoryHelper.cs:212), e.g.LeadUpdatePostOperation. BothPreImageandPostImageare simple type names (Constants.PreImageTypeName = "PreImage",Constants.PostImageTypeName = "PostImage"), so two registrations in the same file both expose aPreImage/PostImagetype.The bug: Today the code fixes try to be clever — they only convert to aliased usings when an ambiguity is detected, otherwise they add a plain (non-aliased)
using. This is driven bySyntaxFactoryHelper.DetectImageAmbiguity(...)(SyntaxFactoryHelper.cs:118):FixHandlerSignatureCodeFixProvider.FixMethodDeclarationsAsync(lines 199–235):ambiguity = DetectImageAmbiguity(...);CreateImageParameterList(hasPreImage, hasPostImage, ambiguity.needsAlias ? ambiguity.alias : null); thenif (ambiguity.needsAlias) ConvertToAliasedUsingsAndQualifyRefs(...) else AddUsingDirectiveIfMissing(...).CreateHandlerMethodCodeFixProvider.CreateMethodAsync(lines 135–152): sameDetectImageAmbiguity/ conditional pattern viaCreateMethodDeclaration(..., needsAlias ? alias : null)and the sameif (needsAlias) ConvertToAliasedUsingsAndQualifyRefs else AddUsingDirectiveIfMissingbranch.When multiple plugins use the same service and more than one of those registrations declares Pre/Post images, the automatic generation of usings and modification of parameters fails, because the plain-using path produces bare
PreImage/PostImagereferences that collide across the multiple image namespaces, and the on-demand conversion logic (ImageAmbiguityRewriter,SyntaxFactoryHelper.cs:234) assumes "there should be exactly one existing plain image using at this point" (SyntaxFactoryHelper.cs:309, thebreak;after taking the first entry of_typeToExistingAlias). That assumption breaks with multiple image usings.The decision: Stop trying to convert on demand. Always emit aliased usings and always qualify the image parameter types with the alias. This makes every emitted reference unambiguous regardless of how many same-service registrations exist in the file.
Existing tests assert the old behavior and must be updated. See:
XrmPluginCore.SourceGenerator.Tests/DiagnosticTests/FixHandlerSignatureCodeFixProviderTests.cs—Should_Fix_Signature_And_Add_Using_For_PreImage(line ~61/64),..._For_PostImage(line ~114/117),..._For_Both_Images(line ~120), andShould_Avoid_Ambiguous_Usings(line 231).XrmPluginCore.SourceGenerator.Tests/DiagnosticTests/CreateHandlerMethodCodeFixProviderTests.cs(same directory).