-
Notifications
You must be signed in to change notification settings - Fork 0
Add: Support fully-registered pre/post images #9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| using Microsoft.CodeAnalysis; | ||
| using Microsoft.CodeAnalysis.CSharp; | ||
| using Microsoft.CodeAnalysis.CSharp.Syntax; | ||
| using Microsoft.CodeAnalysis.Diagnostics; | ||
| using System.Collections.Immutable; | ||
|
|
||
| namespace XrmPluginCore.SourceGenerator.Analyzers; | ||
|
|
||
| /// <summary> | ||
| /// Analyzer that reports XPC3005 when WithPreImage or WithPostImage is called | ||
| /// without specifying any attributes, resulting in a full entity image registration. | ||
| /// </summary> | ||
| [DiagnosticAnalyzer(LanguageNames.CSharp)] | ||
| public class FullEntityImageAnalyzer : DiagnosticAnalyzer | ||
| { | ||
| public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => | ||
| ImmutableArray.Create(DiagnosticDescriptors.FullEntityImage); | ||
|
|
||
| public override void Initialize(AnalysisContext context) | ||
| { | ||
| context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); | ||
| context.EnableConcurrentExecution(); | ||
| context.RegisterSyntaxNodeAction(AnalyzeInvocation, SyntaxKind.InvocationExpression); | ||
| } | ||
|
|
||
| private void AnalyzeInvocation(SyntaxNodeAnalysisContext context) | ||
| { | ||
| var invocation = (InvocationExpressionSyntax)context.Node; | ||
|
|
||
| if (invocation.Expression is not MemberAccessExpressionSyntax memberAccess) | ||
| return; | ||
|
|
||
| var methodName = memberAccess.Name.Identifier.Text; | ||
|
|
||
| if (methodName != Constants.WithPreImageMethodName && methodName != Constants.WithPostImageMethodName) | ||
| return; | ||
|
|
||
| // Only report when called with no arguments (full entity image) | ||
| if (invocation.ArgumentList.Arguments.Count > 0) | ||
| return; | ||
|
|
||
| context.ReportDiagnostic(Diagnostic.Create( | ||
| DiagnosticDescriptors.FullEntityImage, | ||
| invocation.GetLocation(), | ||
| methodName)); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -244,9 +244,29 @@ private static ImageMetadata ParseImageInvocation( | |||||||||
| imageMetadata.ImageName = imageMetadata.ImageType; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| // For WithPreImage/WithPostImage with no attributes specified, capture all entity attributes | ||||||||||
| if (!imageMetadata.Attributes.Any() && | ||||||||||
| (methodName == Constants.WithPreImageMethodName || methodName == Constants.WithPostImageMethodName)) | ||||||||||
| { | ||||||||||
| imageMetadata.Attributes.AddRange(GetAllEntityAttributes(entityType)); | ||||||||||
| } | ||||||||||
|
Comment on lines
+247
to
+252
|
||||||||||
|
|
||||||||||
| return imageMetadata.Attributes.Any() ? imageMetadata : null; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| /// <summary> | ||||||||||
| /// Gets all attribute metadata for all entity properties that have an AttributeLogicalName attribute. | ||||||||||
| /// Used for full entity images where no specific attributes are specified. | ||||||||||
| /// </summary> | ||||||||||
| private static IEnumerable<AttributeMetadata> GetAllEntityAttributes(ITypeSymbol entityType) | ||||||||||
| { | ||||||||||
| return entityType.GetMembers() | ||||||||||
| .OfType<IPropertySymbol>() | ||||||||||
| .Where(p => p.GetAttributes().Any(a => a.AttributeClass?.Name == Constants.LogicalNameAttributeName)) | ||||||||||
| .Select(p => GetAttributeMetadata(p.Name, entityType)) | ||||||||||
| .Where(a => a != null); | ||||||||||
|
||||||||||
| .Where(a => a != null); | |
| .Where(a => a != null) | |
| .OrderBy(a => a.LogicalName, global::System.StringComparer.Ordinal) | |
| .ThenBy(a => a.PropertyName, global::System.StringComparer.Ordinal); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FullEntityImageAnalyzer will report XPC3005 for any method named WithPreImage/WithPostImage anywhere in the codebase (including unrelated user-defined APIs), because it only checks the identifier text and does not verify the invocation is part of an XrmPluginCore RegisterStep fluent chain or that the target symbol is the expected method. This can create false-positive warnings in non-plugin code. Consider restricting analysis to invocations chained from a RegisterStep call (similar to ImageWithoutMethodReferenceAnalyzer) and/or using the semantic model to confirm the invoked IMethodSymbol belongs to the intended XrmPluginCore registration API type/namespace.