using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading; using MapTo.Extensions; using MapTo.Sources; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; namespace MapTo { /// /// MapTo source generator. /// [Generator] public class MapToGenerator : ISourceGenerator { /// public void Initialize(GeneratorInitializationContext context) { context.RegisterForSyntaxNotifications(() => new MapToSyntaxReceiver()); } /// public void Execute(GeneratorExecutionContext context) { try { var options = SourceGenerationOptions.From(context); var compilation = context.Compilation .AddSource(ref context, UseUpdateAttributeSource.Generate(options)) .AddSource(ref context, AddDataAttributeSource.Generate(options)) .AddSource(ref context, JsonExtensionAttributeSource.Generate(options)) .AddSource(ref context, MapFromAttributeSource.Generate(options)) .AddSource(ref context, IgnoreMemberAttributeSource.Generate(options)) .AddSource(ref context, ITypeConverterSource.Generate(options)) .AddSource(ref context, MapTypeConverterAttributeSource.Generate(options)) .AddSource(ref context, MapPropertyAttributeSource.Generate(options)) .AddSource(ref context, MappingContextSource.Generate(options)); if (context.SyntaxReceiver is MapToSyntaxReceiver receiver && receiver.CandidateTypes.Any()) { AddGeneratedMappingsClasses(context, compilation, receiver.CandidateTypes, options); } } catch (Exception ex) { Console.WriteLine(ex); throw; } } private static void AddGeneratedMappingsClasses(GeneratorExecutionContext context, Compilation compilation, IEnumerable candidateTypes, SourceGenerationOptions options) { foreach (var typeDeclarationSyntax in candidateTypes) { var mappingContext = MappingContext.Create(compilation, options, typeDeclarationSyntax); mappingContext.Diagnostics.ForEach(context.ReportDiagnostic); if (mappingContext.Model is null) { continue; } var (source, hintName) = typeDeclarationSyntax switch { StructDeclarationSyntax => MapStructSource.Generate(mappingContext.Model), ClassDeclarationSyntax => MapClassSource.Generate(mappingContext.Model), RecordDeclarationSyntax => MapRecordSource.Generate(mappingContext.Model), _ => throw new ArgumentOutOfRangeException() }; context.AddSource(hintName, source); } } } }