From 1584799bbd61f4b227db2412364b9213895db84c Mon Sep 17 00:00:00 2001 From: Lars Date: Mon, 20 Nov 2023 12:03:13 +0530 Subject: [PATCH] chore: diagnostics refactoring (#919) --- .../Descriptors/DescriptorBuilder.cs | 20 +++++----- .../SimpleMappingBuilderContext.cs | 23 +++-------- .../Diagnostics/DiagnosticCollection.cs | 38 +++++++++++++++++++ src/Riok.Mapperly/MapperGenerator.cs | 4 +- 4 files changed, 54 insertions(+), 31 deletions(-) create mode 100644 src/Riok.Mapperly/Diagnostics/DiagnosticCollection.cs diff --git a/src/Riok.Mapperly/Descriptors/DescriptorBuilder.cs b/src/Riok.Mapperly/Descriptors/DescriptorBuilder.cs index d9c7dd510a..9363ec38f2 100644 --- a/src/Riok.Mapperly/Descriptors/DescriptorBuilder.cs +++ b/src/Riok.Mapperly/Descriptors/DescriptorBuilder.cs @@ -25,7 +25,7 @@ public class DescriptorBuilder private readonly MethodNameBuilder _methodNameBuilder = new(); private readonly MappingBodyBuilder _mappingBodyBuilder; private readonly SimpleMappingBuilderContext _builderContext; - private readonly List _diagnostics = new(); + private readonly DiagnosticCollection _diagnostics; private readonly UnsafeAccessorContext _unsafeAccessorContext; private readonly MapperConfigurationReader _configurationReader; @@ -44,6 +44,7 @@ MapperConfiguration defaultMapperConfiguration var attributeAccessor = new AttributeDataAccessor(symbolAccessor); _configurationReader = new MapperConfigurationReader(attributeAccessor, mapperDeclaration.Symbol, defaultMapperConfiguration); + _diagnostics = new DiagnosticCollection(mapperDeclaration.Syntax.GetLocation()); _builderContext = new SimpleMappingBuilderContext( compilationContext, @@ -58,11 +59,12 @@ MapperConfiguration defaultMapperConfiguration ); } - public (MapperDescriptor descriptor, IReadOnlyCollection diagnostics) Build(CancellationToken cancellationToken) + public (MapperDescriptor descriptor, DiagnosticCollection diagnostics) Build(CancellationToken cancellationToken) { ConfigureMemberVisibility(); ReserveMethodNames(); ExtractUserMappings(); + // ExtractObjectFactories needs to be called after ExtractUserMappings due to configuring mapperDescriptor.Static var objectFactories = ExtractObjectFactories(); EnqueueUserMappings(objectFactories); @@ -93,9 +95,7 @@ private void ConfigureMemberVisibility() if (includedMembers.HasFlag(MemberVisibility.Accessible)) return; - _diagnostics.Add( - Diagnostic.Create(Diagnostics.DiagnosticDescriptors.UnsafeAccessorNotAvailable, _mapperDescriptor.Syntax.GetLocation()) - ); + _diagnostics.ReportDiagnostic(DiagnosticDescriptors.UnsafeAccessorNotAvailable); _symbolAccessor.SetMemberVisibility(includedMembers | MemberVisibility.Accessible); } @@ -131,12 +131,10 @@ private void ExtractUserMappings() if (_mapperDescriptor.Static && firstNonStaticUserMapping is not null) { - _diagnostics.Add( - Diagnostic.Create( - DiagnosticDescriptors.MixingStaticPartialWithInstanceMethod, - firstNonStaticUserMapping.Locations.FirstOrDefault(), - _mapperDescriptor.Symbol.ToDisplayString() - ) + _diagnostics.ReportDiagnostic( + DiagnosticDescriptors.MixingStaticPartialWithInstanceMethod, + firstNonStaticUserMapping, + _mapperDescriptor.Symbol.ToDisplayString() ); } } diff --git a/src/Riok.Mapperly/Descriptors/SimpleMappingBuilderContext.cs b/src/Riok.Mapperly/Descriptors/SimpleMappingBuilderContext.cs index 71e0cc7c90..25e3128e75 100644 --- a/src/Riok.Mapperly/Descriptors/SimpleMappingBuilderContext.cs +++ b/src/Riok.Mapperly/Descriptors/SimpleMappingBuilderContext.cs @@ -2,6 +2,7 @@ using Riok.Mapperly.Abstractions; using Riok.Mapperly.Configuration; using Riok.Mapperly.Descriptors.MappingBuilders; +using Riok.Mapperly.Diagnostics; using Riok.Mapperly.Symbols; namespace Riok.Mapperly.Descriptors; @@ -12,7 +13,7 @@ namespace Riok.Mapperly.Descriptors; public class SimpleMappingBuilderContext { private readonly MapperDescriptor _descriptor; - private readonly List _diagnostics; + private readonly DiagnosticCollection _diagnostics; private readonly CompilationContext _compilationContext; private readonly MapperConfigurationReader _configurationReader; @@ -23,7 +24,7 @@ public SimpleMappingBuilderContext( AttributeDataAccessor attributeAccessor, MapperDescriptor descriptor, UnsafeAccessorContext unsafeAccessorContext, - List diagnostics, + DiagnosticCollection diagnostics, MappingBuilder mappingBuilder, ExistingTargetMappingBuilder existingTargetMappingBuilder ) @@ -73,22 +74,8 @@ protected SimpleMappingBuilderContext(SimpleMappingBuilderContext ctx) public virtual bool IsConversionEnabled(MappingConversionType conversionType) => MapperConfiguration.EnabledConversions.HasFlag(conversionType); - public void ReportDiagnostic(DiagnosticDescriptor descriptor, ISymbol? location, params object[] messageArgs) - { - // cannot use the symbol since it would break the incremental generator - // due to being different for each compilation. - for (var i = 0; i < messageArgs.Length; i++) - { - if (messageArgs[i] is ISymbol symbol) - { - messageArgs[i] = symbol.ToDisplayString(); - } - } - - var syntaxNode = location?.DeclaringSyntaxReferences.FirstOrDefault()?.GetSyntax(); - var nodeLocation = syntaxNode?.GetLocation(); - _diagnostics.Add(Diagnostic.Create(descriptor, nodeLocation ?? _descriptor.Syntax.GetLocation(), messageArgs)); - } + public void ReportDiagnostic(DiagnosticDescriptor descriptor, ISymbol? location, params object[] messageArgs) => + _diagnostics.ReportDiagnostic(descriptor, location, messageArgs); protected MappingConfiguration ReadConfiguration(MappingConfigurationReference configRef) => _configurationReader.BuildFor(configRef); } diff --git a/src/Riok.Mapperly/Diagnostics/DiagnosticCollection.cs b/src/Riok.Mapperly/Diagnostics/DiagnosticCollection.cs new file mode 100644 index 0000000000..e5f0586d38 --- /dev/null +++ b/src/Riok.Mapperly/Diagnostics/DiagnosticCollection.cs @@ -0,0 +1,38 @@ +using System.Collections; +using Microsoft.CodeAnalysis; + +namespace Riok.Mapperly.Diagnostics; + +public class DiagnosticCollection : IReadOnlyCollection +{ + private readonly List _diagnostics = new(); + private readonly Location _defaultLocation; + + internal DiagnosticCollection(Location defaultLocation) + { + _defaultLocation = defaultLocation; + } + + public IEnumerator GetEnumerator() => _diagnostics.GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + public int Count => _diagnostics.Count; + + internal void ReportDiagnostic(DiagnosticDescriptor descriptor, ISymbol? location = null, params object[] messageArgs) + { + // cannot use the symbol since it would break the incremental generator + // due to being different for each compilation. + for (var i = 0; i < messageArgs.Length; i++) + { + if (messageArgs[i] is ISymbol symbol) + { + messageArgs[i] = symbol.ToDisplayString(); + } + } + + var syntaxNode = location?.DeclaringSyntaxReferences.FirstOrDefault()?.GetSyntax(); + var nodeLocation = syntaxNode?.GetLocation(); + _diagnostics.Add(Diagnostic.Create(descriptor, nodeLocation ?? _defaultLocation, messageArgs)); + } +} diff --git a/src/Riok.Mapperly/MapperGenerator.cs b/src/Riok.Mapperly/MapperGenerator.cs index 1631884d3c..18f2462e02 100644 --- a/src/Riok.Mapperly/MapperGenerator.cs +++ b/src/Riok.Mapperly/MapperGenerator.cs @@ -92,12 +92,12 @@ CancellationToken cancellationToken try { var builder = new DescriptorBuilder(compilationContext, mapperDeclaration, symbolAccessor, mapperDefaults); - var (descriptor, descriptorDiagnostics) = builder.Build(cancellationToken); + var (descriptor, diagnostics) = builder.Build(cancellationToken); var mapper = new MapperNode( compilationContext.FileNameBuilder.Build(descriptor), SourceEmitter.Build(descriptor, cancellationToken) ); - return new MapperAndDiagnostics(mapper, descriptorDiagnostics.ToImmutableEquatableArray(), descriptor.RequiredTemplates); + return new MapperAndDiagnostics(mapper, diagnostics.ToImmutableEquatableArray(), descriptor.RequiredTemplates); } catch (OperationCanceledException) {