private static void GenType(EventSourceClass ec, StringBuilder sb) { if (!string.IsNullOrWhiteSpace(ec.Namespace)) { sb.AppendLine($@" namespace {ec.Namespace} {{"); } sb.AppendLine($@" {s_generatedCodeAttribute} partial class {ec.ClassName} {{"); GenerateConstructor(ec, sb); GenerateProviderMetadata(ec.SourceName, sb); sb.AppendLine($@" }}"); if (!string.IsNullOrWhiteSpace(ec.Namespace)) { sb.AppendLine($@" }}"); } }
private void GenType(EventSourceClass ec) { if (!string.IsNullOrWhiteSpace(ec.Namespace)) { _builder.AppendLine($@" namespace {ec.Namespace} {{"); } _builder.AppendLine($@" partial class {ec.ClassName} {{"); GenerateConstructor(ec); GenerateProviderMetadata(ec.SourceName); _builder.AppendLine($@" }}"); if (!string.IsNullOrWhiteSpace(ec.Namespace)) { _builder.AppendLine($@" }}"); } }
private static void EmitSourceFile(SourceProductionContext context, EventSourceClass ec) { StringBuilder sb = new StringBuilder(1024); sb.AppendLine(@"// <auto-generated/>"); sb.AppendLine(); sb.AppendLine("using System;"); GenType(ec, sb); context.AddSource($"{ec.ClassName}.g.cs", SourceText.From(sb.ToString(), Encoding.UTF8)); }
public EventSourceClass[] GetEventSourceClasses(List <ClassDeclarationSyntax> classDeclarations) { INamedTypeSymbol?autogenerateAttribute = _compilation.GetTypeByMetadataName("System.Diagnostics.Tracing.EventSourceAutoGenerateAttribute"); if (autogenerateAttribute is null) { // No EventSourceAutoGenerateAttribute return(Array.Empty <EventSourceClass>()); } INamedTypeSymbol?eventSourceAttribute = _compilation.GetTypeByMetadataName("System.Diagnostics.Tracing.EventSourceAttribute"); if (eventSourceAttribute is null) { // No EventSourceAttribute return(Array.Empty <EventSourceClass>()); } List <EventSourceClass>?results = null; // we enumerate by syntax tree, to minimize the need to instantiate semantic models (since they're expensive) foreach (IGrouping <SyntaxTree, ClassDeclarationSyntax>?group in classDeclarations.GroupBy(x => x.SyntaxTree)) { SemanticModel? sm = null; EventSourceClass?eventSourceClass = null; foreach (ClassDeclarationSyntax?classDef in group) { if (_cancellationToken.IsCancellationRequested) { // be nice and stop if we're asked to return(results?.ToArray() ?? Array.Empty <EventSourceClass>()); } bool autoGenerate = false; foreach (AttributeListSyntax?cal in classDef.AttributeLists) { foreach (AttributeSyntax?ca in cal.Attributes) { // need a semantic model for this tree sm ??= _compilation.GetSemanticModel(classDef.SyntaxTree); if (sm.GetSymbolInfo(ca, _cancellationToken).Symbol is not IMethodSymbol caSymbol) { // badly formed attribute definition, or not the right attribute continue; } if (autogenerateAttribute.Equals(caSymbol.ContainingType, SymbolEqualityComparer.Default)) { autoGenerate = true; continue; } if (eventSourceAttribute.Equals(caSymbol.ContainingType, SymbolEqualityComparer.Default)) { string nspace = string.Empty; NamespaceDeclarationSyntax?ns = classDef.Parent as NamespaceDeclarationSyntax; if (ns is null) { if (classDef.Parent is not CompilationUnitSyntax) { // since this generator doesn't know how to generate a nested type... continue; } } else { nspace = ns.Name.ToString(); while (true) { ns = ns.Parent as NamespaceDeclarationSyntax; if (ns == null) { break; } nspace = $"{ns.Name}.{nspace}"; } } string className = classDef.Identifier.ToString(); string name = className; string guid = ""; SeparatedSyntaxList <AttributeArgumentSyntax>?args = ca.ArgumentList?.Arguments; if (args is not null) { foreach (AttributeArgumentSyntax?arg in args) { string?argName = arg.NameEquals !.Name.Identifier.ToString(); string?value = sm.GetConstantValue(arg.Expression, _cancellationToken).ToString(); switch (argName) { case "Guid": guid = value; break; case "Name": name = value; break; } } } if (!Guid.TryParse(guid, out Guid result)) { result = GenerateGuidFromName(name.ToUpperInvariant()); } eventSourceClass = new EventSourceClass { Namespace = nspace, ClassName = className, SourceName = name, Guid = result }; continue; } } } if (!autoGenerate) { continue; } if (eventSourceClass is null) { continue; } results ??= new List <EventSourceClass>(); results.Add(eventSourceClass); } } return(results?.ToArray() ?? Array.Empty <EventSourceClass>()); }
private static void GenerateConstructor(EventSourceClass ec, StringBuilder sb) { sb.AppendLine($@" private {ec.ClassName}() : base(new Guid({ec.Guid.ToString("x").Replace("{", "").Replace("}", "")}), ""{ec.SourceName}"") {{ }}"); }
private static EventSourceClass?GetSemanticTargetForGeneration(GeneratorAttributeSyntaxContext context, CancellationToken cancellationToken) { const string EventSourceAttribute = "System.Diagnostics.Tracing.EventSourceAttribute"; var classDef = (ClassDeclarationSyntax)context.TargetNode; NamespaceDeclarationSyntax?ns = classDef.Parent as NamespaceDeclarationSyntax; if (ns is null) { if (classDef.Parent is not CompilationUnitSyntax) { // since this generator doesn't know how to generate a nested type... return(null); } } EventSourceClass?eventSourceClass = null; string? nspace = null; foreach (AttributeData attribute in context.TargetSymbol.GetAttributes()) { if (attribute.AttributeClass?.Name != "EventSourceAttribute" || attribute.AttributeClass.ToDisplayString() != EventSourceAttribute) { continue; } nspace ??= ConstructNamespace(ns); string className = classDef.Identifier.ValueText; string name = className; string guid = ""; ImmutableArray <KeyValuePair <string, TypedConstant> > args = attribute.NamedArguments; foreach (KeyValuePair <string, TypedConstant> arg in args) { string argName = arg.Key; string value = arg.Value.Value?.ToString(); switch (argName) { case "Guid": guid = value; break; case "Name": name = value; break; } } if (!Guid.TryParse(guid, out Guid result)) { result = GenerateGuidFromName(name.ToUpperInvariant()); } eventSourceClass = new EventSourceClass(nspace, className, name, result); continue; } return(eventSourceClass); }