public void AddConstants(SyntaxNode attribute, SemanticModel semanticModel, EventSourceTypeInfo eventSourceTypeInfo)
            {
                if (attribute == null)
                   throw new ArgumentNullException("attribute", "attribute is null.");

                AttributeSyntax attributeSyntax;
                AttributeListSyntax attributeListSyntax = attribute as AttributeListSyntax;
                if (attributeListSyntax != null)
                {
                   if (attributeListSyntax.Attributes.Count != 1)
                  throw new GenerationException(attribute.GetLocation(), "Expected a single attribute in attribute list, but either none or more than one were found.");

                   attributeSyntax = attributeListSyntax.Attributes.Single();
                }
                else
                {
                   attributeSyntax = attribute as AttributeSyntax;
                   if (attributeSyntax == null)
                  throw new GenerationException($"SyntaxNode was not of expected type {typeof(AttributeSyntax).FullName}");
                }

                AddToDictionary(attributeSyntax, "Keywords", m_keywords, semanticModel, eventSourceTypeInfo.EventKeywordsType);
                AddToDictionary(attributeSyntax, "Opcode", m_opcodes, semanticModel, eventSourceTypeInfo.EventOpcodeType);
                AddToDictionary(attributeSyntax, "Task", m_tasks, semanticModel, eventSourceTypeInfo.EventTaskType);
            }
            public CollectedGenerationInfo(EventSourceTypeInfo eventSourceTypeInfo)
            {
                if (eventSourceTypeInfo == null)
                   throw new ArgumentNullException("eventSourceTypeInfo", "eventSourceTypeInfo is null.");

                m_eventSourceTypeInfo = eventSourceTypeInfo;
            }
Ejemplo n.º 3
0
            public CollectedGenerationInfo(EventSourceTypeInfo eventSourceTypeInfo)
            {
                if (eventSourceTypeInfo == null)
                {
                    throw new ArgumentNullException("eventSourceTypeInfo", "eventSourceTypeInfo is null.");
                }

                m_eventSourceTypeInfo = eventSourceTypeInfo;
            }
      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);
      }
 /// <summary>
 /// Gets all the attributes from the specified <paramref name="sourceClass"/>, with special handling and translation 
 /// of a TemplateEventSourceAttribute which will be translated into an EventSourceAttribute with additional arguments stripped away.
 /// </summary>
 /// <param name="sourceClass">The clas from which to retrieve and translate attribtues.</param>
 /// <returns>A list of all attributes that should be applied to the target class.</returns>
 private IEnumerable<SyntaxNode> GetClassAttributesWithTranslation(INamedTypeSymbol sourceClass, EventSourceTypeInfo baseTypeInfo)
 {
    foreach (var attributeData in sourceClass.GetAttributes())
    {
       if (attributeData.AttributeClass.Name.Equals(TemplateEventSourceAttributeName))
       {
          yield return m_generator.Attribute(baseTypeInfo.EventSourceAttributeType.GetFullName(),
             attributeData.ConstructorArguments.Select(arg => m_generator.AttributeArgument(m_generator.LiteralExpression(arg.Value)))
             .Concat(
                attributeData.NamedArguments.Where(arg => !typeof(GenerationOptions).GetProperties().Any(p => p.Name.Equals(arg.Key)))
                .Select(arg => m_generator.AttributeArgument(arg.Key, m_generator.LiteralExpression(arg.Value.Value)))
             )
          );
       }
       else
       {
          yield return m_generator.Attribute(attributeData);
       }
    }
 }
      /// <summary>Gets the event source template methods in this collection.</summary>
      /// <param name="sourceClass">The class from which to retrieve methods.</param>
      /// <param name="eventSourceBase">The event source base of the <paramref name="sourceClass"/>.</param>
      /// <returns>
      ///     All methods that are candidates to be used for EventSource generation.
      /// </returns>
      private IEnumerable<IMethodSymbol> GetEventSourceTemplateMethods(INamedTypeSymbol sourceClass, EventSourceTypeInfo eventSourceBase)
      {
         System.Diagnostics.Debug.Assert(sourceClass.IsType);

         foreach (IMethodSymbol method in sourceClass.GetAllMembers().OfType<IMethodSymbol>())
         {
            if (method.GetAttributes().Any(attribute => attribute.AttributeClass.Equals(eventSourceBase.EventAttributeType)) && method.IsAbstract)
            {
               yield return method;
            }
            else if (method.GetAttributes().Any(attribute => attribute.AttributeClass.Name.Equals(TemplateEventAttributeName)))
            {
               if (!method.IsAbstract)
                  throw new CodeGeneratorException(method, $"The method {sourceClass.Name}.{method.Name} must be abstract to participate in EventSource generation.");

               yield return method;
            }
         }
      }
      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 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;
         }
      }
Ejemplo n.º 9
0
            public void AddConstants(SyntaxNode attribute, SemanticModel semanticModel, EventSourceTypeInfo eventSourceTypeInfo)
            {
                if (attribute == null)
                {
                    throw new ArgumentNullException("attribute", "attribute is null.");
                }

                AttributeSyntax     attributeSyntax;
                AttributeListSyntax attributeListSyntax = attribute as AttributeListSyntax;

                if (attributeListSyntax != null)
                {
                    if (attributeListSyntax.Attributes.Count != 1)
                    {
                        throw new CodeGeneratorException(attribute, "Expected a single attribute in attribute list, but either none or more than one were found.");
                    }

                    attributeSyntax = attributeListSyntax.Attributes.Single();
                }
                else
                {
                    attributeSyntax = attribute as AttributeSyntax;
                    if (attributeSyntax == null)
                    {
                        throw new CodeGeneratorException(attribute, $"SyntaxNode was not of expected type {typeof(AttributeSyntax).FullName}");
                    }
                }

                AddToDictionary(attributeSyntax, "Keywords", m_keywords, semanticModel, eventSourceTypeInfo.EventKeywordsType);
                AddToDictionary(attributeSyntax, "Opcode", m_opcodes, semanticModel, eventSourceTypeInfo.EventOpcodeType);
                AddToDictionary(attributeSyntax, "Task", m_tasks, semanticModel, eventSourceTypeInfo.EventTaskType);
            }