private TemplateEventMethodInfo TranslateMethodAttributes(IMethodSymbol sourceMethod, EventSourceTypeInfo eventSourceTypeInfo, CollectedGenerationInfo overloads)
      {
         List<SyntaxNode> attributes = new List<SyntaxNode>();

         SyntaxNode eventAttribute = null;
         int? eventId = null;

         foreach (AttributeData attributeData in sourceMethod.GetAttributes())
         {
            var attributeClass = attributeData.AttributeClass;

            if (attributeClass.Name.Equals(TemplateEventAttributeName) || attributeClass.Equals(eventSourceTypeInfo.EventAttributeType))
            {               
               SyntaxNode attributeSyntax = attributeData.ApplicationSyntaxReference?.GetSyntax();
               if (attributeSyntax == null)
                  throw new CodeGeneratorException(sourceMethod, $"Cannot find the source file containing the method {sourceMethod.Name}. The source code must be available for any Template EventSource class to participate in generation. Is the project unloaded?");

               Document attributeDocument = m_document.Project.Solution.GetDocument(attributeSyntax.SyntaxTree);
               if (attributeDocument == null)
                  throw new CodeGeneratorException(sourceMethod, $"Cannot find the document containing the method {sourceMethod.Name}.");

               
               overloads.AddConstants(attributeSyntax, attributeDocument.GetSemanticModelAsync().Result, eventSourceTypeInfo);

               attributeSyntax = m_generator.Attribute(eventSourceTypeInfo.EventAttributeType.GetFullName(), m_generator.GetAttributeArguments(attributeSyntax));
                  
               attributes.Add(attributeSyntax);


               TypedConstant eventIdArgument = attributeData.ConstructorArguments.FirstOrDefault();
               if (attributeData.ConstructorArguments.Length == 0)
                  throw new CodeGeneratorException(sourceMethod, $"The {attributeData.AttributeClass.Name} attribute must have an event ID as its first argument.");

               if (!(eventIdArgument.Value is int))
                  throw new CodeGeneratorException(sourceMethod, $"The first argument to the {attributeData.AttributeClass.Name} attribute must be of type Int32.");

               eventId = (int)eventIdArgument.Value;
               eventAttribute = attributeSyntax;
            }
            else
            {
               attributes.Add(CreateAttribute(attributeData));                  
            }
         }

         if (eventAttribute == null)
            throw new CodeGeneratorException(sourceMethod, $"Internal error; Unable to find EventAttribute or TemplateEventAttribute on method {sourceMethod.Name}");

         if (eventId == null)
            throw new CodeGeneratorException(sourceMethod, $"Unable to determine EventId for method {sourceMethod.Name}");

         return new TemplateEventMethodInfo(attributes, eventId.Value);
      }
      private IEnumerable<SyntaxNode> GenerateEventSourceMethods(INamedTypeSymbol sourceClass, EventSourceTypeInfo eventSourceTypeInfo, CollectedGenerationInfo overloads, GenerationOptions options)
      {
         var templateMethods = GetEventSourceTemplateMethods(sourceClass, eventSourceTypeInfo);
         foreach (var sourceMethodEntry in templateMethods.AsSmartEnumerable())
         {
            IMethodSymbol sourceMethod = sourceMethodEntry.Value;

            TemplateEventMethodInfo eventAttributeInfo = TranslateMethodAttributes(sourceMethod, eventSourceTypeInfo, overloads);

            WriteEventOverloadInfo overloadInfo = new WriteEventOverloadInfo(sourceMethodEntry.Value, options, m_parameterConverters);

            if (overloadInfo.Parameters.Any(p => p.IsSupported == false))
            {
               throw new CodeGeneratorException(sourceMethod, $"The parameter(s) {StringUtils.Join(overloadInfo.Parameters.Where(p => !p.IsSupported).Select(p => $"{p.Parameter.Name} ({p.Parameter.Type.Name})"), ", ", " and ")} are not supported.");
            }

            overloads.TryAdd(overloadInfo);

            // Check if this method has needs a wrapper method to perform parameter conversion into a natively supported parameter type.            
            if (overloadInfo.NeedsConverter)
            {
               // Create the wrapper method
               SyntaxNode wrapperMethod = m_generator.MethodDeclaration(sourceMethod);
               
               // This method should only have the [NonEvent] attribute.
               wrapperMethod = m_generator.AddAttributes(m_generator.RemoveAllAttributes(wrapperMethod), m_generator.Attribute(eventSourceTypeInfo.EventSourceNamespace.GetFullName() + ".NonEvent"));

               wrapperMethod = m_generator.WithAccessibility(wrapperMethod, sourceMethod.DeclaredAccessibility);
               wrapperMethod = m_generator.WithModifiers(wrapperMethod, DeclarationModifiers.Override);

               // And it should call the overload of the same method that is generated below (the actual event method)
               wrapperMethod = m_generator.WithStatements(wrapperMethod,
                  new[]
                  {
                     m_generator.IfStatement(
                        // Condition
                        m_generator.InvocationExpression(m_generator.IdentifierName("IsEnabled")),

                        // True-Statements
                        new[]
                        {
                           m_generator.ExpressionStatement(
                              m_generator.InvocationExpression(m_generator.IdentifierName(sourceMethod.Name),
                                 overloadInfo.Parameters.Select(parameter => m_generator.Argument(
                                          parameter.HasConverter ?
                                             parameter.Converter.GetConversionExpression(m_generator.IdentifierName(parameter.Parameter.Name)) :
                                             m_generator.IdentifierName(parameter.Parameter.Name)
                                    )
                                 )
                              )
                           )
                        }
                     )
                  }
               );

               // And let's add some warning comments about this being generated code.
               wrapperMethod = wrapperMethod.WithLeadingTrivia(wrapperMethod.GetLeadingTrivia().AddRange(CreateWarningComment()));

               yield return wrapperMethod;
            }

            // Generate the actual event method.
            SyntaxNode eventMethod = m_generator.MethodDeclaration(sourceMethod.Name);

            if (overloadInfo.NeedsConverter)
            {
               // If we have a wrapper method converting parameters, this will be a private method.
               eventMethod = m_generator.WithAccessibility(eventMethod, Accessibility.Private);
            }
            else
            {
               // Otherwise it has the same accessibility as the base class method, except this is an override of course.
               eventMethod = m_generator.WithAccessibility(eventMethod, sourceMethod.DeclaredAccessibility);
               eventMethod = m_generator.WithModifiers(eventMethod, DeclarationModifiers.Override);
            }

            // The parameter list may be modified from the source method to account for any conversions performed by the wrapper method.
            eventMethod = m_generator.AddParameters(eventMethod,
               overloadInfo.Parameters.Select(pi => m_generator.ParameterDeclaration(pi.Parameter.Name, m_generator.TypeExpression(pi.TargetType)))
            );

            // Statement to call the WriteEvent() method.
            SyntaxNode writeEventStatement = m_generator.ExpressionStatement(
                                       m_generator.InvocationExpression(m_generator.IdentifierName("WriteEvent"),
                                          new[] {
                                             m_generator.Argument(m_generator.LiteralExpression(eventAttributeInfo.EventId)),
                                          }.Concat(overloadInfo.Parameters.Select(parameter => m_generator.Argument(
                                                        m_generator.IdentifierName(parameter.Parameter.Name))
                                             )
                                          )
                                       )
                                    );

            if (overloadInfo.NeedsConverter)
            {
               // If this method has a wrapper method, then the IsEnabled() check has already been made, so we skip that here
               // and just call the WriteEvent() method.
               eventMethod = m_generator.WithStatements(eventMethod, new[] { writeEventStatement });
            }
            else
            {
               // Otherwise we want to check the IsEnabled() flag first.
               eventMethod = m_generator.WithStatements(eventMethod,
                  new[]
                  {
                     m_generator.IfStatement(
                        // Condition
                        m_generator.InvocationExpression(m_generator.IdentifierName("IsEnabled")),

                        // True-Statements
                        new[]
                        {
                           writeEventStatement
                        }
                     )
                  }
               );
            }

            // Add all attributes from the source method. (Well, with translation of the TemplateEventAttribute).
            eventMethod = m_generator.AddAttributes(eventMethod, eventAttributeInfo.Attributes);

            // And some warning comments as usual.
            eventMethod = eventMethod.WithLeadingTrivia(eventMethod.GetLeadingTrivia().AddRange(CreateWarningComment()));

            yield return eventMethod;
         }
      }
      private ClassDeclarationSyntax GenerateEventSourceClass(INamedTypeSymbol sourceClass)
      {
         if (sourceClass.IsGenericType)
            throw new CodeGeneratorException(sourceClass, $"The template class '{sourceClass.Name}' for generating an EventSource implementation must not be generic.");

         if (!sourceClass.IsAbstract)
            throw new CodeGeneratorException(sourceClass, $"The class '{sourceClass.Name}' must be abstract to participate in EventSource implementation generation.");

         ValidateReservedMemberName(sourceClass, "Opcodes");
         ValidateReservedMemberName(sourceClass, "Keywords");
         ValidateReservedMemberName(sourceClass, "Tasks");

         GenerationOptions options = ParseGenerationOptions(sourceClass);

         EventSourceTypeInfo eventSourceTypeInfo = GetEventSourceBaseTypeInfo(sourceClass);

         IEnumerable<SyntaxNode> translatedAttributes = GetClassAttributesWithTranslation(sourceClass, eventSourceTypeInfo);

         var asms = AppDomain.CurrentDomain.GetAssemblies().OrderBy(asm => asm.FullName).ToArray();

         var targetClass = m_generator.ClassDeclaration(
            name: options.TargetClassName,
            baseType: m_generator.IdentifierName(sourceClass.Name),
            accessibility: sourceClass.DeclaredAccessibility == Accessibility.Public ? Accessibility.Public : Accessibility.Internal,
            modifiers: DeclarationModifiers.Sealed
         );

         targetClass = m_generator.AddAttributes(targetClass, translatedAttributes);
         var overloads = new CollectedGenerationInfo(eventSourceTypeInfo);
         ImmutableArray<SyntaxNode> eventSourceMethods = GenerateEventSourceMethods(sourceClass, eventSourceTypeInfo, overloads, options).ToImmutableArray();

         if (eventSourceMethods.Length > 0)
         {
            eventSourceMethods = eventSourceMethods.SetItem(0, eventSourceMethods[0].PrependLeadingTrivia(CreateRegionTriviaList("Event Methods")));
            eventSourceMethods = eventSourceMethods.SetItem(eventSourceMethods.Length - 1, eventSourceMethods.Last().WithTrailingTrivia(CreateEndRegionTriviaList().Add(SF.EndOfLine(Environment.NewLine)).Add(SF.EndOfLine(Environment.NewLine))));
         }

         targetClass = m_generator.AddMembers(targetClass, eventSourceMethods);

         if (!options.SuppressSingletonGeneration)
            targetClass = m_generator.InsertMembers(targetClass, 0, CreateSingletonProperty(sourceClass, options));

         targetClass = targetClass.WithLeadingTrivia(CreateWarningComment());

         if (options.AllowUnsafeCode)
         {
            var writeEventMethods = GenerateWriteEventOverloads(overloads, options, eventSourceTypeInfo).ToImmutableArray();

            if (writeEventMethods.Length > 0)
            {
               writeEventMethods = writeEventMethods.SetItem(0, writeEventMethods[0].PrependLeadingTrivia(CreateRegionTriviaList("WriteEvent Overloads")));
               writeEventMethods = writeEventMethods.SetItem(writeEventMethods.Length - 1, writeEventMethods.Last().WithTrailingTrivia(CreateEndRegionTriviaList().Add(SF.EndOfLine(Environment.NewLine)).Add(SF.EndOfLine(Environment.NewLine))));
            }

            targetClass = m_generator.AddMembers(targetClass, writeEventMethods);
         }

         if (overloads.Keywords.Count > 0)
            targetClass = m_generator.AddMembers(targetClass, GenerateConstantsClass("Keywords", overloads.Keywords, m_compilation.GetTypeByMetadataName(eventSourceTypeInfo.EventSourceNamespace.GetFullName() + ".EventKeywords")));

         if (overloads.Opcodes.Count > 0)
            targetClass = m_generator.AddMembers(targetClass, GenerateConstantsClass("Opcodes", overloads.Opcodes, m_compilation.GetTypeByMetadataName(eventSourceTypeInfo.EventSourceNamespace.GetFullName() + ".EventOpcode")));

         if (overloads.Tasks.Count > 0)
            targetClass = m_generator.AddMembers(targetClass, GenerateConstantsClass("Tasks", overloads.Tasks, m_compilation.GetTypeByMetadataName(eventSourceTypeInfo.EventSourceNamespace.GetFullName() + ".EventTask")));

         // Add GeneratedCode attribute to the target class.
         targetClass = m_generator.AddAttributes(targetClass, 
                                                 m_generator.Attribute(typeof(System.CodeDom.Compiler.GeneratedCodeAttribute).FullName, 
                                                      m_generator.AttributeArgument(m_generator.LiteralExpression(Assembly.GetExecutingAssembly().GetCustomAttribute<AssemblyTitleAttribute>()?.Title)), 
                                                      m_generator.AttributeArgument(m_generator.LiteralExpression(Assembly.GetExecutingAssembly().GetName().Version.ToString()))));

         return (ClassDeclarationSyntax)targetClass;
      }
      private IEnumerable<SyntaxNode> GenerateWriteEventOverloads(CollectedGenerationInfo overloads, GenerationOptions options, EventSourceTypeInfo eventSourceTypeInfo)
      {
         foreach (WriteEventOverloadInfo overload in overloads.Overloads)
         {
            SyntaxNode method = m_generator.MethodDeclaration("WriteEvent",
               new[] { m_generator.ParameterDeclaration("eventId", m_generator.TypeExpression(SpecialType.System_Int32)) }
               .Concat(overload.Parameters.Select((pi, idx) => m_generator.ParameterDeclaration($"arg{idx}", m_generator.TypeExpression(pi.TargetType)))),
               accessibility: Accessibility.Private);

            method = WithUnsafeModifier(method);

            method = m_generator.AddAttributes(method, m_generator.Attribute(
               m_generator.TypeExpression(
                  m_semanticModel.Compilation.GetTypeByMetadataName(eventSourceTypeInfo.EventSourceNamespace.GetFullName() + ".NonEventAttribute")
               )));
            List<SyntaxNode> statements = new List<SyntaxNode>();

            for (int i = 0; i < overload.Parameters.Length; i++)
            {
               if (overload.Parameters[i].TargetType.SpecialType == SpecialType.System_String)
               {
                  statements.Add(m_generator.IfStatement(m_generator.ReferenceEqualsExpression(m_generator.IdentifierName($"arg{i}"), m_generator.NullLiteralExpression()),
                     new[]
                     {
                        m_generator.AssignmentStatement(m_generator.IdentifierName($"arg{i}"),
                           m_generator.MemberAccessExpression(m_generator.TypeExpression(SpecialType.System_String), "Empty")
                        )
                     }
                  ));
               }
               else if (overload.Parameters[i].TargetType.TypeKind == TypeKind.Array && ((IArrayTypeSymbol)overload.Parameters[i].TargetType).ElementType.SpecialType == SpecialType.System_Byte)
               {
                  statements.Add(m_generator.IfStatement(m_generator.ReferenceEqualsExpression(m_generator.IdentifierName($"arg{i}"), m_generator.NullLiteralExpression()),
                     new[]
                     {
                        m_generator.AssignmentStatement(m_generator.IdentifierName($"arg{i}"),
                           m_generator.ArrayCreationExpression(
                              m_generator.TypeExpression(SpecialType.System_Byte),
                              m_generator.LiteralExpression(0)
                           )
                        )
                     }
                  ));
               }
               else if (overload.Parameters[i].TargetType.SpecialType == SpecialType.System_DateTime)
               {
                  statements.Add(
                     m_generator.LocalDeclarationStatement(
                        m_generator.TypeExpression(SpecialType.System_Int64),
                        $"fileTime{i}",
                        m_generator.InvocationExpression(
                           m_generator.MemberAccessExpression(
                              m_generator.IdentifierName($"arg{i}"),
                              m_generator.IdentifierName("ToFileTimeUtc")
                           )
                        )
                     )
                  );
               }
               else if (overload.Parameters[i].TargetType.TypeKind == TypeKind.Enum)
               {
                  INamedTypeSymbol namedTypeSymbol = (INamedTypeSymbol)overload.Parameters[i].TargetType;
                  statements.Add(
                     m_generator.LocalDeclarationStatement(
                        m_generator.TypeExpression(namedTypeSymbol.EnumUnderlyingType),
                        $"enumValue{i}",
                        m_generator.CastExpression(
                           m_generator.TypeExpression(namedTypeSymbol.EnumUnderlyingType),
                           m_generator.IdentifierName($"arg{i}")
                        )
                     )
                  );
               }
            }

            // Descriptor length. A byte-array actually takes up two descriptor-slots (length + data), so we calculate the total size here.");
            int descrLength = overload.Parameters.Select(pi => pi.TargetType.IsByteArray() ? 2 : 1).Sum();

            string eventDataTypeFullName = eventSourceTypeInfo.EventSourceClass.GetFullName() + "+EventData";
            INamedTypeSymbol eventDataType = m_compilation.GetTypeByMetadataName(eventDataTypeFullName);
            if (eventDataType == null)
               throw new CodeGeneratorException($"Failed to lookup type {eventDataTypeFullName}.");

            TypeSyntax eventDataTypeSyntax = (TypeSyntax)m_generator.TypeExpression(eventDataType);

            //EventData* descrs = stackalloc EventData[{descrLength}];
            statements.Add(
               SF.LocalDeclarationStatement(
                  SF.VariableDeclaration(
                     SF.PointerType(
                        eventDataTypeSyntax
                     ),
                     SF.SingletonSeparatedList(
                        SF.VariableDeclarator(
                           SF.Identifier("descrs"),
                           null,
                           SF.EqualsValueClause(
                              SF.Token(SyntaxKind.EqualsToken),
                              SF.StackAllocArrayCreationExpression(
                                 SF.ArrayType(
                                    eventDataTypeSyntax,
                                    SF.SingletonList(
                                       SF.ArrayRankSpecifier(
                                          SF.SingletonSeparatedList(
                                             m_generator.LiteralExpression(descrLength) as ExpressionSyntax
                                          )
                                       )
                                    )
                                 )
                              )
                           )
                        )
                     )
                  )
               )
            );


            List<SyntaxNode> innerStatements = new List<SyntaxNode>();
            int descrPos = 0;
            for (int i = 0; i < overload.Parameters.Length; i++, descrPos++)
            {
               if (overload.Parameters[i].TargetType.IsByteArray())
               {
                  // ==> int length{i} = arg{i}.Length;
                  innerStatements.Add(
                     m_generator.LocalDeclarationStatement(
                        m_generator.TypeExpression(SpecialType.System_Int32),
                        $"length{i}",
                        m_generator.MemberAccessExpression(m_generator.IdentifierName($"arg{i}"), "Length")
                     )
                  );

                  // ==> descrs[{descrPos}].DataPointer = (IntPtr)(&length{i});
                  innerStatements.Add(
                     AssignDescrSyntax("descrs", descrPos, "DataPointer", AddressOfVariableAsIntPtrSyntax($"length{i}"))
                  );

                  // ==> descrs[{descrPos}].Size = 4;
                  innerStatements.Add(
                     AssignDescrSyntax("descrs", descrPos, "Size", m_generator.LiteralExpression(4))
                  );

                  descrPos++;

                  // ==> descrs[{descrPos}].DataPointer = (IntPtr)bin{i}
                  innerStatements.Add(
                     AssignDescrSyntax("descrs", descrPos, "DataPointer", m_generator.CastExpression(IntPtrType, m_generator.IdentifierName($"bin{i}")))
                  );

                  // ==> descrs[{descrPos}].Size = length{i}
                  innerStatements.Add(
                     AssignDescrSyntax("descrs", descrPos, "Size", m_generator.IdentifierName($"length{i}"))
                  );
               }
               else if (overload.Parameters[i].TargetType.SpecialType == SpecialType.System_String)
               {
                  // ==> descrs[{descrPos}].DataPointer = (IntPtr)str{i}
                  innerStatements.Add(
                     AssignDescrSyntax("descrs", descrPos, "DataPointer", m_generator.CastExpression(IntPtrType, m_generator.IdentifierName($"str{i}")))
                  );

                  // ==> descrs[{descrPos}].Size = (arg{i}.Length + 1) * 2;
                  innerStatements.Add(
                     AssignDescrSyntax("descrs", descrPos, "Size",
                        m_generator.MultiplyExpression(
                           m_generator.AddExpression(
                              m_generator.MemberAccessExpression(
                                 m_generator.IdentifierName($"arg{i}"),
                                 m_generator.IdentifierName($"Length")
                              ),
                              m_generator.LiteralExpression(1)
                           ),
                           m_generator.LiteralExpression(2)
                        )
                     )
                  );
               }
               else if (overload.Parameters[i].TargetType.SpecialType == SpecialType.System_DateTime)
               {
                  // ==> descrs[{descrPos}].DataPointer = (IntPtr)(&fileTime{i});
                  innerStatements.Add(
                     AssignDescrSyntax("descrs", descrPos, "DataPointer", AddressOfVariableAsIntPtrSyntax($"fileTime{i}"))
                  );

                  // ==> descrs[{descrPos}].Size = 8;
                  innerStatements.Add(
                     AssignDescrSyntax("descrs", descrPos, "Size", m_generator.LiteralExpression(8))
                  );
               }
               else if (overload.Parameters[i].TargetType.TypeKind == TypeKind.Enum)
               {
                  INamedTypeSymbol namedTypeSymbol = (INamedTypeSymbol)overload.Parameters[i].TargetType;
                  // ==> descrs[{descrPos}].DataPointer = (IntPtr)(&enumValue{i});
                  innerStatements.Add(
                     AssignDescrSyntax("descrs", descrPos, "DataPointer", AddressOfVariableAsIntPtrSyntax($"enumValue{i}"))
                  );

                  // ==> descrs[{descrPos}].Size = 8;
                  innerStatements.Add(
                     AssignDescrSyntax("descrs", descrPos, "Size", GetTypeSize(overload.Parameters[i].TargetType))
                  );
               }
               else
               {
                  // ==> descrs[{descrPos}].DataPointer = (IntPtr)(&arg{i});
                  innerStatements.Add(
                     AssignDescrSyntax("descrs", descrPos, "DataPointer", AddressOfVariableAsIntPtrSyntax($"arg{i}"))
                  );

                  // ==> descrs[{descrPos}].Size = 8;
                  innerStatements.Add(
                     AssignDescrSyntax("descrs", descrPos, "Size", GetTypeSize(overload.Parameters[i].TargetType))
                  );

               }
            }

            innerStatements.Add(
               m_generator.ExpressionStatement(
                  m_generator.InvocationExpression(
                     m_generator.IdentifierName("WriteEventCore"),
                     m_generator.IdentifierName("eventId"),
                     m_generator.LiteralExpression(descrLength),
                     m_generator.IdentifierName("descrs")
                  )
               )
            );
           
            // Create fixed statements
            BlockSyntax fixedContent = SF.Block(innerStatements.Cast<StatementSyntax>());

            FixedStatementSyntax fixedStatementSyntax = null;
            for (int i = 0; i < overload.Parameters.Length; i++)
            {
               FixedStatementSyntax current = null;
               if (overload.Parameters[i].TargetType.SpecialType == SpecialType.System_String)
               {
                  current = GetFixedStatement(SyntaxKind.CharKeyword, fixedContent, $"str{i}", $"arg{i}");
               }
               else if (overload.Parameters[i].TargetType.IsByteArray())
               {
                  current = GetFixedStatement(SyntaxKind.ByteKeyword, fixedContent, $"bin{i}", $"arg{i}");
               }

               if (current != null)
               {
                  if (fixedStatementSyntax == null)
                  {
                     fixedStatementSyntax = current;
                  }
                  else
                  {
                     fixedStatementSyntax = current.WithStatement(SF.Block(fixedStatementSyntax));
                  }
               }

            }

            if (fixedStatementSyntax != null)
            {
               statements.Add(fixedStatementSyntax);
            }
            else
            {
               statements.Add(fixedContent);
            }

            method = m_generator.WithStatements(method, statements);

            method = method.PrependLeadingTrivia(CreateWarningComment());

            yield return method;
         }
      }
      private SyntaxNode GenerateEventSourceClass(INamedTypeSymbol sourceClass)
      {
         if (sourceClass.IsGenericType)
            throw new GenerationException(sourceClass, $"The template class '{sourceClass.Name}' for generating an EventSource implementation must not be generic.");

         if (!sourceClass.IsAbstract)
            throw new GenerationException(sourceClass, $"The class '{sourceClass.Name}' must be abstract to participate in EventSource implementation generation.");

         GenerationOptions options = ParseGenerationOptions(sourceClass);

         EventSourceTypeInfo eventSourceTypeInfo = GetEventSourceBaseTypeInfo(sourceClass);

         IEnumerable<SyntaxNode> translatedAttributes = GetClassAttributesWithTranslation(sourceClass, eventSourceTypeInfo);

         var asms = AppDomain.CurrentDomain.GetAssemblies().OrderBy(asm => asm.FullName).ToArray();

         var targetClass = m_generator.ClassDeclaration(
            name: options.TargetClassName,
            baseType: m_generator.IdentifierName(sourceClass.Name),
            accessibility: sourceClass.DeclaredAccessibility == Accessibility.Public ? Accessibility.Public : Accessibility.Internal,
            modifiers: DeclarationModifiers.Sealed
         );

         targetClass = m_generator.AddAttributes(targetClass, translatedAttributes);
         var overloads = new CollectedGenerationInfo(eventSourceTypeInfo);
         var eventSourceMethods = GenerateEventSourceMethods(sourceClass, eventSourceTypeInfo, overloads, options).ToImmutableArray();

         if (eventSourceMethods.Length > 0)
         {
            eventSourceMethods = eventSourceMethods.SetItem(0, eventSourceMethods[0].WithLeadingTrivia(CreateRegionTriviaList("Event Methods")));
            eventSourceMethods = eventSourceMethods.SetItem(eventSourceMethods.Length - 1, eventSourceMethods.Last().WithTrailingTrivia(CreateEndRegionTriviaList()));
         }

         targetClass = m_generator.AddMembers(targetClass, eventSourceMethods);

         if (!options.SuppressSingletonGeneration)
            targetClass = m_generator.InsertMembers(targetClass, 0, CreateSingletonProperty(sourceClass, options));

         targetClass = targetClass.WithLeadingTrivia(CreateWarningComment());

         var writeEventMethods = GenerateWriteEventOverloads(overloads, options, eventSourceTypeInfo).ToImmutableArray();

         if (writeEventMethods.Length > 0)
         {
            writeEventMethods = writeEventMethods.SetItem(0, writeEventMethods[0].WithLeadingTrivia(CreateRegionTriviaList("WriteEvent Overloads")));
            writeEventMethods = writeEventMethods.SetItem(writeEventMethods.Length - 1, writeEventMethods.Last().WithTrailingTrivia(CreateEndRegionTriviaList()));
         }

         targetClass = m_generator.AddMembers(targetClass, writeEventMethods);

         targetClass = m_generator.AddMembers(targetClass,
            new SyntaxNode[]
            {
               GenerateConstantsClass("Keywords", overloads.Keywords, m_compilation.GetTypeByMetadataName(eventSourceTypeInfo.EventSourceNamespace.GetFullName() + ".EventKeywords")),
               GenerateConstantsClass("Opcodes", overloads.Opcodes, m_compilation.GetTypeByMetadataName(eventSourceTypeInfo.EventSourceNamespace.GetFullName() + ".EventOpcode")),
               GenerateConstantsClass("Tasks", overloads.Tasks, m_compilation.GetTypeByMetadataName(eventSourceTypeInfo.EventSourceNamespace.GetFullName() + ".EventTask"))
            });

         return targetClass;
      }