From 420a45c633e9b83e30b4d04fbc8bfc450c411b26 Mon Sep 17 00:00:00 2001 From: Theodore Tsirpanis Date: Mon, 31 Jan 2022 23:58:46 +0200 Subject: [PATCH 1/8] Mark the EventSource generator's output as auto-generated. Fixes #64563. --- .../gen/EventSourceGenerator.Emitter.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Emitter.cs b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Emitter.cs index 894ae45816ad38..9c71cd0378f01b 100644 --- a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Emitter.cs +++ b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Emitter.cs @@ -12,6 +12,12 @@ namespace Generators { public partial class EventSourceGenerator { + /// Code for a [GeneratedCode] attribute to put on the top-level generated members. + private static readonly string s_generatedCodeAttribute = $"[global::System.CodeDom.Compiler.GeneratedCodeAttribute(\"{typeof(EventSourceGenerator).Assembly.GetName().Name}\", \"{typeof(EventSourceGenerator).Assembly.GetName().Version}\")]"; + /// Header comments and usings to include at the top of every generated file. + private static readonly string s_header = + "// " + Environment.NewLine; + private sealed class Emitter { private readonly StringBuilder _builder = new StringBuilder(1024); @@ -29,6 +35,7 @@ public void Emit(EventSourceClass[] eventSources, CancellationToken cancellation break; } + _builder.AppendLine(s_header); _builder.AppendLine("using System;"); GenType(ec); @@ -48,6 +55,7 @@ namespace {ec.Namespace} } _builder.AppendLine($@" + {s_generatedCodeAttribute} partial class {ec.ClassName} {{"); GenerateConstructor(ec); From 46d7495c0d42b4f5c1882fb41996bc61119434f6 Mon Sep 17 00:00:00 2001 From: Theodore Tsirpanis Date: Tue, 1 Feb 2022 01:13:35 +0200 Subject: [PATCH 2/8] Make the EventSource generator incremental. --- .../gen/EventSourceGenerator.Emitter.cs | 52 +++++------- .../gen/EventSourceGenerator.Parser.cs | 52 +++++------- .../gen/EventSourceGenerator.cs | 84 ++++++++----------- 3 files changed, 75 insertions(+), 113 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Emitter.cs b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Emitter.cs index 9c71cd0378f01b..8c2ea325d9d04a 100644 --- a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Emitter.cs +++ b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Emitter.cs @@ -20,76 +20,64 @@ public partial class EventSourceGenerator private sealed class Emitter { - private readonly StringBuilder _builder = new StringBuilder(1024); - private readonly GeneratorExecutionContext _context; - - public Emitter(GeneratorExecutionContext context) => _context = context; - - public void Emit(EventSourceClass[] eventSources, CancellationToken cancellationToken) + public static void Emit(SourceProductionContext spc, EventSourceClass ec) { - foreach (EventSourceClass? ec in eventSources) - { - if (cancellationToken.IsCancellationRequested) - { - // stop any additional work - break; - } + StringBuilder sb = new StringBuilder(1024); - _builder.AppendLine(s_header); - _builder.AppendLine("using System;"); - GenType(ec); + sb.AppendLine(s_header); + sb.AppendLine("using System;"); + GenType(ec, sb); - _context.AddSource($"{ec.ClassName}.g.cs", SourceText.From(_builder.ToString(), Encoding.UTF8)); + spc.AddSource($"{ec.ClassName}.g.cs", SourceText.From(sb.ToString(), Encoding.UTF8)); - _builder.Clear(); - } + sb.Clear(); } - private void GenType(EventSourceClass ec) + private static void GenType(EventSourceClass ec, StringBuilder sb) { if (!string.IsNullOrWhiteSpace(ec.Namespace)) { - _builder.AppendLine($@" + sb.AppendLine($@" namespace {ec.Namespace} {{"); } - _builder.AppendLine($@" + sb.AppendLine($@" {s_generatedCodeAttribute} partial class {ec.ClassName} {{"); - GenerateConstructor(ec); + GenerateConstructor(ec, sb); - GenerateProviderMetadata(ec.SourceName); + GenerateProviderMetadata(ec.SourceName, sb); - _builder.AppendLine($@" + sb.AppendLine($@" }}"); if (!string.IsNullOrWhiteSpace(ec.Namespace)) { - _builder.AppendLine($@" + sb.AppendLine($@" }}"); } } - private void GenerateConstructor(EventSourceClass ec) + private static void GenerateConstructor(EventSourceClass ec, StringBuilder sb) { - _builder.AppendLine($@" + sb.AppendLine($@" private {ec.ClassName}() : base(new Guid({ec.Guid.ToString("x").Replace("{", "").Replace("}", "")}), ""{ec.SourceName}"") {{ }}"); } - private void GenerateProviderMetadata(string sourceName) + private static void GenerateProviderMetadata(string sourceName, StringBuilder sb) { - _builder.Append(@" + sb.Append(@" private protected override ReadOnlySpan ProviderMetadata => new byte[] { "); byte[] metadataBytes = MetadataForString(sourceName); foreach (byte b in metadataBytes) { - _builder.Append($"0x{b:x}, "); + sb.Append($"0x{b:x}, "); } - _builder.AppendLine(@"};"); + sb.AppendLine(@"};"); } // From System.Private.CoreLib diff --git a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Parser.cs b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Parser.cs index 2b28b46e03335b..bce7d7da3a18ed 100644 --- a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Parser.cs +++ b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Parser.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.Linq; using System.Security.Cryptography; using System.Text; @@ -16,58 +17,47 @@ namespace Generators { public partial class EventSourceGenerator { - private sealed class Parser + private static class Parser { - private readonly CancellationToken _cancellationToken; - private readonly Compilation _compilation; - private readonly Action _reportDiagnostic; - - public Parser(Compilation compilation, Action reportDiagnostic, CancellationToken cancellationToken) - { - _compilation = compilation; - _cancellationToken = cancellationToken; - _reportDiagnostic = reportDiagnostic; - } - - public EventSourceClass[] GetEventSourceClasses(List classDeclarations) + public static ImmutableArray GetEventSourceClasses(ImmutableArray classDeclarations, Compilation compilation, CancellationToken ct) { - INamedTypeSymbol? autogenerateAttribute = _compilation.GetBestTypeByMetadataName("System.Diagnostics.Tracing.EventSourceAutoGenerateAttribute"); + INamedTypeSymbol? autogenerateAttribute = compilation.GetBestTypeByMetadataName("System.Diagnostics.Tracing.EventSourceAutoGenerateAttribute"); if (autogenerateAttribute is null) { // No EventSourceAutoGenerateAttribute - return Array.Empty(); + return ImmutableArray.Empty; } - INamedTypeSymbol? eventSourceAttribute = _compilation.GetBestTypeByMetadataName("System.Diagnostics.Tracing.EventSourceAttribute"); + INamedTypeSymbol? eventSourceAttribute = compilation.GetBestTypeByMetadataName("System.Diagnostics.Tracing.EventSourceAttribute"); if (eventSourceAttribute is null) { // No EventSourceAttribute - return Array.Empty(); + return ImmutableArray.Empty; } - List? results = null; + ImmutableArray.Builder? results = null; // we enumerate by syntax tree, to minimize the need to instantiate semantic models (since they're expensive) - foreach (IGrouping? group in classDeclarations.GroupBy(x => x.SyntaxTree)) + foreach (IGrouping group in classDeclarations.GroupBy(static x => x.SyntaxTree)) { SemanticModel? sm = null; EventSourceClass? eventSourceClass = null; - foreach (ClassDeclarationSyntax? classDef in group) + foreach (ClassDeclarationSyntax classDef in group) { - if (_cancellationToken.IsCancellationRequested) + if (ct.IsCancellationRequested) { // be nice and stop if we're asked to - return results?.ToArray() ?? Array.Empty(); + return results?.ToImmutable() ?? ImmutableArray.Empty; } bool autoGenerate = false; - foreach (AttributeListSyntax? cal in classDef.AttributeLists) + foreach (AttributeListSyntax cal in classDef.AttributeLists) { - foreach (AttributeSyntax? ca in cal.Attributes) + foreach (AttributeSyntax ca in cal.Attributes) { // need a semantic model for this tree - sm ??= _compilation.GetSemanticModel(classDef.SyntaxTree); + sm ??= compilation.GetSemanticModel(classDef.SyntaxTree); - if (sm.GetSymbolInfo(ca, _cancellationToken).Symbol is not IMethodSymbol caSymbol) + if (sm.GetSymbolInfo(ca, ct).Symbol is not IMethodSymbol caSymbol) { // badly formed attribute definition, or not the right attribute continue; @@ -112,10 +102,10 @@ public EventSourceClass[] GetEventSourceClasses(List cla SeparatedSyntaxList? args = ca.ArgumentList?.Arguments; if (args is not null) { - foreach (AttributeArgumentSyntax? arg in args) + foreach (AttributeArgumentSyntax arg in args) { - string? argName = arg.NameEquals!.Name.Identifier.ToString(); - string? value = sm.GetConstantValue(arg.Expression, _cancellationToken).ToString(); + string argName = arg.NameEquals!.Name.Identifier.ToString(); + string value = sm.GetConstantValue(arg.Expression, ct).ToString(); switch (argName) { @@ -156,12 +146,12 @@ public EventSourceClass[] GetEventSourceClasses(List cla continue; } - results ??= new List(); + results ??= ImmutableArray.CreateBuilder(); results.Add(eventSourceClass); } } - return results?.ToArray() ?? Array.Empty(); + return results?.ToImmutable() ?? ImmutableArray.Empty; } // From System.Private.CoreLib diff --git a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.cs b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.cs index a86fef7e38ced7..ba29c0b1a331cd 100644 --- a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.cs +++ b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.cs @@ -10,7 +10,7 @@ namespace Generators { [Generator] - public partial class EventSourceGenerator : ISourceGenerator + public partial class EventSourceGenerator : IIncrementalGenerator { // Example input: // @@ -32,69 +32,53 @@ public partial class EventSourceGenerator : ISourceGenerator // } // } - public void Initialize(GeneratorInitializationContext context) - => context.RegisterForSyntaxNotifications(() => new SyntaxReceiver()); - - public void Execute(GeneratorExecutionContext context) + public void Initialize(IncrementalGeneratorInitializationContext context) { - SyntaxReceiver? receiver = context.SyntaxReceiver as SyntaxReceiver; - if ((receiver?.CandidateClasses?.Count ?? 0) == 0) - { - // nothing to do yet - return; - } + IncrementalValuesProvider eventSourceClasses = + context.SyntaxProvider + .CreateSyntaxProvider(static (x, _) => IsSyntaxTargetForGeneration(x), (x, _) => GetSemanticTargetForGeneration(x)) + .Where(x => x is not null) + .Collect() + .Combine(context.CompilationProvider) + .SelectMany((x, ct) => Parser.GetEventSourceClasses(x.Left, x.Right, ct)); - Parser? p = new Parser(context.Compilation, context.ReportDiagnostic, context.CancellationToken); - EventSourceClass[]? eventSources = p.GetEventSourceClasses(receiver.CandidateClasses); - - if (eventSources?.Length > 0) - { - Emitter? e = new Emitter(context); - e.Emit(eventSources, context.CancellationToken); - } + context.RegisterSourceOutput(eventSourceClasses, static (spc, x) => Emitter.Emit(spc, x)); } - private sealed class SyntaxReceiver : ISyntaxReceiver + private static bool IsSyntaxTargetForGeneration(SyntaxNode node) => + node is ClassDeclarationSyntax x && x.AttributeLists.Count > 0; + + private static ClassDeclarationSyntax? GetSemanticTargetForGeneration(GeneratorSyntaxContext context) { - private List? _candidateClasses; + // Only add classes annotated [EventSourceAutoGenerate] to reduce busy work. + const string EventSourceAttribute = "EventSourceAutoGenerateAttribute"; + const string EventSourceAttributeShort = "EventSourceAutoGenerate"; - public List? CandidateClasses => _candidateClasses; + var classDeclaration = (ClassDeclarationSyntax)context.Node; - public void OnVisitSyntaxNode(SyntaxNode syntaxNode) + // Check if has EventSource attribute before adding to candidates + // as we don't want to add every class in the project + foreach (AttributeListSyntax? cal in classDeclaration.AttributeLists) { - // Only add classes annotated [EventSourceAutoGenerate] to reduce busy work. - const string EventSourceAttribute = "EventSourceAutoGenerateAttribute"; - const string EventSourceAttributeShort = "EventSourceAutoGenerate"; - - // Only classes - if (syntaxNode is ClassDeclarationSyntax classDeclaration) + foreach (AttributeSyntax? ca in cal.Attributes) { - // Check if has EventSource attribute before adding to candidates - // as we don't want to add every class in the project - foreach (AttributeListSyntax? cal in classDeclaration.AttributeLists) + // Check if Span length matches before allocating the string to check more + int length = ca.Name.Span.Length; + if (length != EventSourceAttribute.Length && length != EventSourceAttributeShort.Length) { - foreach (AttributeSyntax? ca in cal.Attributes) - { - // Check if Span length matches before allocating the string to check more - int length = ca.Name.Span.Length; - if (length != EventSourceAttribute.Length && length != EventSourceAttributeShort.Length) - { - continue; - } + continue; + } - // Possible match, now check the string value - string attrName = ca.Name.ToString(); - if (attrName == EventSourceAttribute || attrName == EventSourceAttributeShort) - { - // Match add to candidates - _candidateClasses ??= new List(); - _candidateClasses.Add(classDeclaration); - return; - } - } + // Possible match, now check the string value + string attrName = ca.Name.ToString(); + if (attrName == EventSourceAttribute || attrName == EventSourceAttributeShort) + { + return classDeclaration; } } } + + return null; } private sealed class EventSourceClass From 575f4a60a73948acd4414e309b4b1a150f48a9b8 Mon Sep 17 00:00:00 2001 From: Theodore Tsirpanis Date: Sat, 5 Feb 2022 20:57:10 +0200 Subject: [PATCH 3/8] Address PR feedback. --- .../gen/EventSourceGenerator.Emitter.cs | 10 ++--- .../gen/EventSourceGenerator.Parser.cs | 8 ++-- .../gen/EventSourceGenerator.cs | 44 ++++++++++++++++++- 3 files changed, 50 insertions(+), 12 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Emitter.cs b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Emitter.cs index 8c2ea325d9d04a..66e38cb32f1226 100644 --- a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Emitter.cs +++ b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Emitter.cs @@ -14,23 +14,19 @@ public partial class EventSourceGenerator { /// Code for a [GeneratedCode] attribute to put on the top-level generated members. private static readonly string s_generatedCodeAttribute = $"[global::System.CodeDom.Compiler.GeneratedCodeAttribute(\"{typeof(EventSourceGenerator).Assembly.GetName().Name}\", \"{typeof(EventSourceGenerator).Assembly.GetName().Version}\")]"; - /// Header comments and usings to include at the top of every generated file. - private static readonly string s_header = - "// " + Environment.NewLine; - private sealed class Emitter + private static class Emitter { public static void Emit(SourceProductionContext spc, EventSourceClass ec) { StringBuilder sb = new StringBuilder(1024); - sb.AppendLine(s_header); + sb.AppendLine(@"// "); + sb.AppendLine(); sb.AppendLine("using System;"); GenType(ec, sb); spc.AddSource($"{ec.ClassName}.g.cs", SourceText.From(sb.ToString(), Encoding.UTF8)); - - sb.Clear(); } private static void GenType(EventSourceClass ec, StringBuilder sb) diff --git a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Parser.cs b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Parser.cs index bce7d7da3a18ed..848d0dd0495a99 100644 --- a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Parser.cs +++ b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Parser.cs @@ -19,7 +19,7 @@ public partial class EventSourceGenerator { private static class Parser { - public static ImmutableArray GetEventSourceClasses(ImmutableArray classDeclarations, Compilation compilation, CancellationToken ct) + public static ImmutableArray GetEventSourceClasses(ImmutableArray classDeclarations, Compilation compilation, CancellationToken cancellationToken) { INamedTypeSymbol? autogenerateAttribute = compilation.GetBestTypeByMetadataName("System.Diagnostics.Tracing.EventSourceAutoGenerateAttribute"); if (autogenerateAttribute is null) @@ -43,7 +43,7 @@ public static ImmutableArray GetEventSourceClasses(ImmutableAr EventSourceClass? eventSourceClass = null; foreach (ClassDeclarationSyntax classDef in group) { - if (ct.IsCancellationRequested) + if (cancellationToken.IsCancellationRequested) { // be nice and stop if we're asked to return results?.ToImmutable() ?? ImmutableArray.Empty; @@ -57,7 +57,7 @@ public static ImmutableArray GetEventSourceClasses(ImmutableAr // need a semantic model for this tree sm ??= compilation.GetSemanticModel(classDef.SyntaxTree); - if (sm.GetSymbolInfo(ca, ct).Symbol is not IMethodSymbol caSymbol) + if (sm.GetSymbolInfo(ca, cancellationToken).Symbol is not IMethodSymbol caSymbol) { // badly formed attribute definition, or not the right attribute continue; @@ -105,7 +105,7 @@ public static ImmutableArray GetEventSourceClasses(ImmutableAr foreach (AttributeArgumentSyntax arg in args) { string argName = arg.NameEquals!.Name.Identifier.ToString(); - string value = sm.GetConstantValue(arg.Expression, ct).ToString(); + string value = sm.GetConstantValue(arg.Expression, cancellationToken).ToString(); switch (argName) { diff --git a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.cs b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.cs index ba29c0b1a331cd..e434a9b133315e 100644 --- a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.cs +++ b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Collections.Immutable; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; @@ -40,7 +41,9 @@ public void Initialize(IncrementalGeneratorInitializationContext context) .Where(x => x is not null) .Collect() .Combine(context.CompilationProvider) - .SelectMany((x, ct) => Parser.GetEventSourceClasses(x.Left, x.Right, ct)); + // Use a custom comparer that ignores the compilation. + .WithComparer(ClassDeclarationsEqualityComparer.Instance) + .SelectMany((x, cancellationToken) => Parser.GetEventSourceClasses(x.Left, x.Right, cancellationToken)); context.RegisterSourceOutput(eventSourceClasses, static (spc, x) => Emitter.Emit(spc, x)); } @@ -81,6 +84,45 @@ private static bool IsSyntaxTargetForGeneration(SyntaxNode node) => return null; } + private sealed class ClassDeclarationsEqualityComparer : IEqualityComparer<(ImmutableArray Left, Compilation Right)> + { + public static readonly ClassDeclarationsEqualityComparer Instance = new(); + + private ClassDeclarationsEqualityComparer() { } + + public bool Equals((ImmutableArray, Compilation) x, (ImmutableArray, Compilation) y) + { + var array1 = x.Item1; + var array2 = y.Item1; + + if (array1.Length != array2.Length) + return false; + for (int i = 0; i < array1.Length; i++) + { + if (!array1[i].Equals(array2[i])) + { + return false; + } + } + + return true; + } + public int GetHashCode((ImmutableArray, Compilation) obj) + { + // Numbers taken from the FNV prime and offset basis. + int hash = -2128831035; + foreach (ClassDeclarationSyntax x in obj.Item1) + { + // The implementation is not correct in the strict + // sense, since it needs to process each byte individually. + // But never mind, we are combining reference-based hash codes. + hash ^= x.GetHashCode(); + hash *= 16777619; + } + return hash; + } + } + private sealed class EventSourceClass { public string Namespace = string.Empty; From 3a5f850222a8a0eecc8801fa570070e53b019bff Mon Sep 17 00:00:00 2001 From: Theodore Tsirpanis Date: Tue, 8 Feb 2022 00:35:24 +0200 Subject: [PATCH 4/8] Move the semantic checks and data gathering earlier in the pipeline. The code was significantly shrunk. --- .../gen/EventSourceGenerator.Parser.cs | 190 ++++++++---------- .../gen/EventSourceGenerator.cs | 86 +------- 2 files changed, 85 insertions(+), 191 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Parser.cs b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Parser.cs index 848d0dd0495a99..2fc0cad3d28a0a 100644 --- a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Parser.cs +++ b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Parser.cs @@ -19,139 +19,113 @@ public partial class EventSourceGenerator { private static class Parser { - public static ImmutableArray GetEventSourceClasses(ImmutableArray classDeclarations, Compilation compilation, CancellationToken cancellationToken) + public static bool IsSyntaxTargetForGeneration(SyntaxNode node) => + node is ClassDeclarationSyntax x && x.AttributeLists.Count > 0; + + public static EventSourceClass? GetSemanticTargetForGeneration(GeneratorSyntaxContext context, CancellationToken cancellationToken) { - INamedTypeSymbol? autogenerateAttribute = compilation.GetBestTypeByMetadataName("System.Diagnostics.Tracing.EventSourceAutoGenerateAttribute"); - if (autogenerateAttribute is null) - { - // No EventSourceAutoGenerateAttribute - return ImmutableArray.Empty; - } + const string EventSourceAutoGenerateAttribute = "System.Diagnostics.Tracing.EventSourceAutoGenerateAttribute"; + const string EventSourceAttribute = "System.Diagnostics.Tracing.EventSourceAttribute"; - INamedTypeSymbol? eventSourceAttribute = compilation.GetBestTypeByMetadataName("System.Diagnostics.Tracing.EventSourceAttribute"); - if (eventSourceAttribute is null) - { - // No EventSourceAttribute - return ImmutableArray.Empty; - } + var classDef = (ClassDeclarationSyntax)context.Node; + SemanticModel sm = context.SemanticModel; + EventSourceClass? eventSourceClass = null; - ImmutableArray.Builder? results = null; - // we enumerate by syntax tree, to minimize the need to instantiate semantic models (since they're expensive) - foreach (IGrouping group in classDeclarations.GroupBy(static x => x.SyntaxTree)) + bool autoGenerate = false; + foreach (AttributeListSyntax cal in classDef.AttributeLists) { - SemanticModel? sm = null; - EventSourceClass? eventSourceClass = null; - foreach (ClassDeclarationSyntax classDef in group) + foreach (AttributeSyntax ca in cal.Attributes) { - if (cancellationToken.IsCancellationRequested) + if (sm.GetSymbolInfo(ca, cancellationToken).Symbol is not IMethodSymbol caSymbol) { - // be nice and stop if we're asked to - return results?.ToImmutable() ?? ImmutableArray.Empty; + // badly formed attribute definition, or not the right attribute + continue; } - bool autoGenerate = false; - foreach (AttributeListSyntax cal in classDef.AttributeLists) + string attributeFullName = caSymbol.ContainingType.ToDisplayString(); + + if (attributeFullName.Equals(EventSourceAutoGenerateAttribute, StringComparison.Ordinal)) { - foreach (AttributeSyntax ca in cal.Attributes) - { - // need a semantic model for this tree - sm ??= compilation.GetSemanticModel(classDef.SyntaxTree); + autoGenerate = true; + continue; + } - if (sm.GetSymbolInfo(ca, cancellationToken).Symbol is not IMethodSymbol caSymbol) - { - // badly formed attribute definition, or not the right attribute - continue; - } + if (!attributeFullName.Equals(EventSourceAttribute, StringComparison.Ordinal)) + { + 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) { - 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? 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; + break; } + + nspace = $"{ns.Name}.{nspace}"; } } - if (!autoGenerate) + string className = classDef.Identifier.ToString(); + string name = className; + string guid = ""; + + SeparatedSyntaxList? args = ca.ArgumentList?.Arguments; + if (args is not null) { - continue; + 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 (eventSourceClass is null) + if (!Guid.TryParse(guid, out Guid result)) { - continue; + result = GenerateGuidFromName(name.ToUpperInvariant()); } - results ??= ImmutableArray.CreateBuilder(); - results.Add(eventSourceClass); + eventSourceClass = new EventSourceClass + { + Namespace = nspace, + ClassName = className, + SourceName = name, + Guid = result + }; + continue; } } - return results?.ToImmutable() ?? ImmutableArray.Empty; + if (!autoGenerate) + { + return null; + } + + return eventSourceClass; } // From System.Private.CoreLib diff --git a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.cs b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.cs index e434a9b133315e..4aff822a8da4a7 100644 --- a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.cs +++ b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.cs @@ -4,7 +4,7 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; - +using System.Threading; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; @@ -37,92 +37,12 @@ public void Initialize(IncrementalGeneratorInitializationContext context) { IncrementalValuesProvider eventSourceClasses = context.SyntaxProvider - .CreateSyntaxProvider(static (x, _) => IsSyntaxTargetForGeneration(x), (x, _) => GetSemanticTargetForGeneration(x)) - .Where(x => x is not null) - .Collect() - .Combine(context.CompilationProvider) - // Use a custom comparer that ignores the compilation. - .WithComparer(ClassDeclarationsEqualityComparer.Instance) - .SelectMany((x, cancellationToken) => Parser.GetEventSourceClasses(x.Left, x.Right, cancellationToken)); + .CreateSyntaxProvider(static (x, _) => Parser.IsSyntaxTargetForGeneration(x), (x, cancellationToken) => Parser.GetSemanticTargetForGeneration(x, cancellationToken)) + .Where(x => x is not null); context.RegisterSourceOutput(eventSourceClasses, static (spc, x) => Emitter.Emit(spc, x)); } - private static bool IsSyntaxTargetForGeneration(SyntaxNode node) => - node is ClassDeclarationSyntax x && x.AttributeLists.Count > 0; - - private static ClassDeclarationSyntax? GetSemanticTargetForGeneration(GeneratorSyntaxContext context) - { - // Only add classes annotated [EventSourceAutoGenerate] to reduce busy work. - const string EventSourceAttribute = "EventSourceAutoGenerateAttribute"; - const string EventSourceAttributeShort = "EventSourceAutoGenerate"; - - var classDeclaration = (ClassDeclarationSyntax)context.Node; - - // Check if has EventSource attribute before adding to candidates - // as we don't want to add every class in the project - foreach (AttributeListSyntax? cal in classDeclaration.AttributeLists) - { - foreach (AttributeSyntax? ca in cal.Attributes) - { - // Check if Span length matches before allocating the string to check more - int length = ca.Name.Span.Length; - if (length != EventSourceAttribute.Length && length != EventSourceAttributeShort.Length) - { - continue; - } - - // Possible match, now check the string value - string attrName = ca.Name.ToString(); - if (attrName == EventSourceAttribute || attrName == EventSourceAttributeShort) - { - return classDeclaration; - } - } - } - - return null; - } - - private sealed class ClassDeclarationsEqualityComparer : IEqualityComparer<(ImmutableArray Left, Compilation Right)> - { - public static readonly ClassDeclarationsEqualityComparer Instance = new(); - - private ClassDeclarationsEqualityComparer() { } - - public bool Equals((ImmutableArray, Compilation) x, (ImmutableArray, Compilation) y) - { - var array1 = x.Item1; - var array2 = y.Item1; - - if (array1.Length != array2.Length) - return false; - for (int i = 0; i < array1.Length; i++) - { - if (!array1[i].Equals(array2[i])) - { - return false; - } - } - - return true; - } - public int GetHashCode((ImmutableArray, Compilation) obj) - { - // Numbers taken from the FNV prime and offset basis. - int hash = -2128831035; - foreach (ClassDeclarationSyntax x in obj.Item1) - { - // The implementation is not correct in the strict - // sense, since it needs to process each byte individually. - // But never mind, we are combining reference-based hash codes. - hash ^= x.GetHashCode(); - hash *= 16777619; - } - return hash; - } - } - private sealed class EventSourceClass { public string Namespace = string.Empty; From ea0d09f8b11750a5d1387aa99b5bbefb65f53e5a Mon Sep 17 00:00:00 2001 From: Theodore Tsirpanis Date: Tue, 8 Feb 2022 00:43:02 +0200 Subject: [PATCH 5/8] Stop nesting classes inside the generator. Not actually needed, and reduces indentation. --- .../gen/EventSourceGenerator.Emitter.cs | 105 +++++----- .../gen/EventSourceGenerator.Parser.cs | 195 +++++++++--------- .../gen/EventSourceGenerator.cs | 4 +- 3 files changed, 149 insertions(+), 155 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Emitter.cs b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Emitter.cs index 66e38cb32f1226..fdca6af76e6e81 100644 --- a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Emitter.cs +++ b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Emitter.cs @@ -15,86 +15,83 @@ public partial class EventSourceGenerator /// Code for a [GeneratedCode] attribute to put on the top-level generated members. private static readonly string s_generatedCodeAttribute = $"[global::System.CodeDom.Compiler.GeneratedCodeAttribute(\"{typeof(EventSourceGenerator).Assembly.GetName().Name}\", \"{typeof(EventSourceGenerator).Assembly.GetName().Version}\")]"; - private static class Emitter + private static void EmitSourceFile(SourceProductionContext spc, EventSourceClass ec) { - public static void Emit(SourceProductionContext spc, EventSourceClass ec) - { - StringBuilder sb = new StringBuilder(1024); + StringBuilder sb = new StringBuilder(1024); - sb.AppendLine(@"// "); - sb.AppendLine(); - sb.AppendLine("using System;"); - GenType(ec, sb); + sb.AppendLine(@"// "); + sb.AppendLine(); + sb.AppendLine("using System;"); + GenType(ec, sb); - spc.AddSource($"{ec.ClassName}.g.cs", SourceText.From(sb.ToString(), Encoding.UTF8)); - } + spc.AddSource($"{ec.ClassName}.g.cs", SourceText.From(sb.ToString(), Encoding.UTF8)); + } - private static void GenType(EventSourceClass ec, StringBuilder sb) + private static void GenType(EventSourceClass ec, StringBuilder sb) + { + if (!string.IsNullOrWhiteSpace(ec.Namespace)) { - if (!string.IsNullOrWhiteSpace(ec.Namespace)) - { - sb.AppendLine($@" + sb.AppendLine($@" namespace {ec.Namespace} {{"); - } + } - sb.AppendLine($@" + sb.AppendLine($@" {s_generatedCodeAttribute} partial class {ec.ClassName} {{"); - GenerateConstructor(ec, sb); + GenerateConstructor(ec, sb); - GenerateProviderMetadata(ec.SourceName, sb); + GenerateProviderMetadata(ec.SourceName, sb); - sb.AppendLine($@" + sb.AppendLine($@" }}"); - if (!string.IsNullOrWhiteSpace(ec.Namespace)) - { - sb.AppendLine($@" + if (!string.IsNullOrWhiteSpace(ec.Namespace)) + { + sb.AppendLine($@" }}"); - } } + } - private static void GenerateConstructor(EventSourceClass ec, StringBuilder sb) - { - sb.AppendLine($@" + 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 void GenerateProviderMetadata(string sourceName, StringBuilder sb) - { - sb.Append(@" + private static void GenerateProviderMetadata(string sourceName, StringBuilder sb) + { + sb.Append(@" private protected override ReadOnlySpan ProviderMetadata => new byte[] { "); - byte[] metadataBytes = MetadataForString(sourceName); - foreach (byte b in metadataBytes) - { - sb.Append($"0x{b:x}, "); - } - - sb.AppendLine(@"};"); - } - - // From System.Private.CoreLib - private static byte[] MetadataForString(string name) + byte[] metadataBytes = MetadataForString(sourceName); + foreach (byte b in metadataBytes) { - CheckName(name); - int metadataSize = Encoding.UTF8.GetByteCount(name) + 3; - byte[]? metadata = new byte[metadataSize]; - ushort totalSize = checked((ushort)(metadataSize)); - metadata[0] = unchecked((byte)totalSize); - metadata[1] = unchecked((byte)(totalSize >> 8)); - Encoding.UTF8.GetBytes(name, 0, name.Length, metadata, 2); - return metadata; + sb.Append($"0x{b:x}, "); } - private static void CheckName(string? name) + sb.AppendLine(@"};"); + } + + // From System.Private.CoreLib + private static byte[] MetadataForString(string name) + { + CheckName(name); + int metadataSize = Encoding.UTF8.GetByteCount(name) + 3; + byte[]? metadata = new byte[metadataSize]; + ushort totalSize = checked((ushort)(metadataSize)); + metadata[0] = unchecked((byte)totalSize); + metadata[1] = unchecked((byte)(totalSize >> 8)); + Encoding.UTF8.GetBytes(name, 0, name.Length, metadata, 2); + return metadata; + } + + private static void CheckName(string? name) + { + if (name != null && 0 <= name.IndexOf('\0')) { - if (name != null && 0 <= name.IndexOf('\0')) - { - throw new ArgumentOutOfRangeException(nameof(name)); - } + throw new ArgumentOutOfRangeException(nameof(name)); } } } diff --git a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Parser.cs b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Parser.cs index 2fc0cad3d28a0a..ea1e25f789cf5e 100644 --- a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Parser.cs +++ b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Parser.cs @@ -17,143 +17,140 @@ namespace Generators { public partial class EventSourceGenerator { - private static class Parser - { - public static bool IsSyntaxTargetForGeneration(SyntaxNode node) => - node is ClassDeclarationSyntax x && x.AttributeLists.Count > 0; + private static bool IsSyntaxTargetForGeneration(SyntaxNode node) => + node is ClassDeclarationSyntax x && x.AttributeLists.Count > 0; - public static EventSourceClass? GetSemanticTargetForGeneration(GeneratorSyntaxContext context, CancellationToken cancellationToken) - { - const string EventSourceAutoGenerateAttribute = "System.Diagnostics.Tracing.EventSourceAutoGenerateAttribute"; - const string EventSourceAttribute = "System.Diagnostics.Tracing.EventSourceAttribute"; + private static EventSourceClass? GetSemanticTargetForGeneration(GeneratorSyntaxContext context, CancellationToken cancellationToken) + { + const string EventSourceAutoGenerateAttribute = "System.Diagnostics.Tracing.EventSourceAutoGenerateAttribute"; + const string EventSourceAttribute = "System.Diagnostics.Tracing.EventSourceAttribute"; - var classDef = (ClassDeclarationSyntax)context.Node; - SemanticModel sm = context.SemanticModel; - EventSourceClass? eventSourceClass = null; + var classDef = (ClassDeclarationSyntax)context.Node; + SemanticModel sm = context.SemanticModel; + EventSourceClass? eventSourceClass = null; - bool autoGenerate = false; - foreach (AttributeListSyntax cal in classDef.AttributeLists) + bool autoGenerate = false; + foreach (AttributeListSyntax cal in classDef.AttributeLists) + { + foreach (AttributeSyntax ca in cal.Attributes) { - foreach (AttributeSyntax ca in cal.Attributes) + if (sm.GetSymbolInfo(ca, cancellationToken).Symbol is not IMethodSymbol caSymbol) { - if (sm.GetSymbolInfo(ca, cancellationToken).Symbol is not IMethodSymbol caSymbol) - { - // badly formed attribute definition, or not the right attribute - continue; - } + // badly formed attribute definition, or not the right attribute + continue; + } - string attributeFullName = caSymbol.ContainingType.ToDisplayString(); + string attributeFullName = caSymbol.ContainingType.ToDisplayString(); - if (attributeFullName.Equals(EventSourceAutoGenerateAttribute, StringComparison.Ordinal)) - { - autoGenerate = true; - continue; - } + if (attributeFullName.Equals(EventSourceAutoGenerateAttribute, StringComparison.Ordinal)) + { + autoGenerate = true; + continue; + } - if (!attributeFullName.Equals(EventSourceAttribute, StringComparison.Ordinal)) + if (!attributeFullName.Equals(EventSourceAttribute, StringComparison.Ordinal)) + { + continue; + } + + 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; } - - string nspace = string.Empty; - NamespaceDeclarationSyntax? ns = classDef.Parent as NamespaceDeclarationSyntax; - if (ns is null) + } + else + { + nspace = ns.Name.ToString(); + while (true) { - if (classDef.Parent is not CompilationUnitSyntax) + ns = ns.Parent as NamespaceDeclarationSyntax; + if (ns == null) { - // since this generator doesn't know how to generate a nested type... - continue; + break; } - } - else - { - nspace = ns.Name.ToString(); - while (true) - { - ns = ns.Parent as NamespaceDeclarationSyntax; - if (ns == null) - { - break; - } - nspace = $"{ns.Name}.{nspace}"; - } + nspace = $"{ns.Name}.{nspace}"; } + } - string className = classDef.Identifier.ToString(); - string name = className; - string guid = ""; + string className = classDef.Identifier.ToString(); + string name = className; + string guid = ""; - SeparatedSyntaxList? args = ca.ArgumentList?.Arguments; - if (args is not null) + SeparatedSyntaxList? args = ca.ArgumentList?.Arguments; + if (args is not null) + { + foreach (AttributeArgumentSyntax arg in args) { - foreach (AttributeArgumentSyntax arg in args) + string argName = arg.NameEquals!.Name.Identifier.ToString(); + string value = sm.GetConstantValue(arg.Expression, cancellationToken).ToString(); + + switch (argName) { - 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; - } + 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 (!Guid.TryParse(guid, out Guid result)) + { + result = GenerateGuidFromName(name.ToUpperInvariant()); } - } - if (!autoGenerate) - { - return null; + eventSourceClass = new EventSourceClass + { + Namespace = nspace, + ClassName = className, + SourceName = name, + Guid = result + }; + continue; } + } - return eventSourceClass; + if (!autoGenerate) + { + return null; } - // From System.Private.CoreLib - private static Guid GenerateGuidFromName(string name) + return eventSourceClass; + } + + // From System.Private.CoreLib + private static Guid GenerateGuidFromName(string name) + { + ReadOnlySpan namespaceBytes = new byte[] // rely on C# compiler optimization to remove byte[] allocation { - ReadOnlySpan namespaceBytes = new byte[] // rely on C# compiler optimization to remove byte[] allocation - { 0x48, 0x2C, 0x2D, 0xB2, 0xC3, 0x90, 0x47, 0xC8, 0x87, 0xF8, 0x1A, 0x15, 0xBF, 0xC1, 0x30, 0xFB, - }; + }; - byte[] bytes = Encoding.BigEndianUnicode.GetBytes(name); + byte[] bytes = Encoding.BigEndianUnicode.GetBytes(name); - byte[] combinedBytes = new byte[namespaceBytes.Length + bytes.Length]; + byte[] combinedBytes = new byte[namespaceBytes.Length + bytes.Length]; - bytes.CopyTo(combinedBytes, namespaceBytes.Length); - namespaceBytes.CopyTo(combinedBytes); + bytes.CopyTo(combinedBytes, namespaceBytes.Length); + namespaceBytes.CopyTo(combinedBytes); - using (SHA1 sha = SHA1.Create()) - { - bytes = sha.ComputeHash(combinedBytes); - } + using (SHA1 sha = SHA1.Create()) + { + bytes = sha.ComputeHash(combinedBytes); + } - Array.Resize(ref bytes, 16); + Array.Resize(ref bytes, 16); - bytes[7] = unchecked((byte)((bytes[7] & 0x0F) | 0x50)); // Set high 4 bits of octet 7 to 5, as per RFC 4122 - return new Guid(bytes); - } + bytes[7] = unchecked((byte)((bytes[7] & 0x0F) | 0x50)); // Set high 4 bits of octet 7 to 5, as per RFC 4122 + return new Guid(bytes); } } } diff --git a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.cs b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.cs index 4aff822a8da4a7..0feecb7e45586c 100644 --- a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.cs +++ b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.cs @@ -37,10 +37,10 @@ public void Initialize(IncrementalGeneratorInitializationContext context) { IncrementalValuesProvider eventSourceClasses = context.SyntaxProvider - .CreateSyntaxProvider(static (x, _) => Parser.IsSyntaxTargetForGeneration(x), (x, cancellationToken) => Parser.GetSemanticTargetForGeneration(x, cancellationToken)) + .CreateSyntaxProvider(static (x, _) => IsSyntaxTargetForGeneration(x), (x, cancellationToken) => GetSemanticTargetForGeneration(x, cancellationToken)) .Where(x => x is not null); - context.RegisterSourceOutput(eventSourceClasses, static (spc, x) => Emitter.Emit(spc, x)); + context.RegisterSourceOutput(eventSourceClasses, static (spc, x) => EmitSourceFile(spc, x)); } private sealed class EventSourceClass From 9d0112bddd59beaddf66dc77743e20033b6256d8 Mon Sep 17 00:00:00 2001 From: Theodore Tsirpanis Date: Tue, 8 Feb 2022 02:21:12 +0200 Subject: [PATCH 6/8] Address remaining PR feedback. Make EventSourceClass a record, use method groups instead of lambdas, and rename a parameter. --- .../gen/EventSourceGenerator.Emitter.cs | 4 ++-- .../gen/EventSourceGenerator.Parser.cs | 12 +++--------- .../gen/EventSourceGenerator.cs | 12 +++--------- .../gen/System.Private.CoreLib.Generators.csproj | 1 + 4 files changed, 9 insertions(+), 20 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Emitter.cs b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Emitter.cs index fdca6af76e6e81..2dcedb1b435ce8 100644 --- a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Emitter.cs +++ b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Emitter.cs @@ -15,7 +15,7 @@ public partial class EventSourceGenerator /// Code for a [GeneratedCode] attribute to put on the top-level generated members. private static readonly string s_generatedCodeAttribute = $"[global::System.CodeDom.Compiler.GeneratedCodeAttribute(\"{typeof(EventSourceGenerator).Assembly.GetName().Name}\", \"{typeof(EventSourceGenerator).Assembly.GetName().Version}\")]"; - private static void EmitSourceFile(SourceProductionContext spc, EventSourceClass ec) + private static void EmitSourceFile(SourceProductionContext context, EventSourceClass ec) { StringBuilder sb = new StringBuilder(1024); @@ -24,7 +24,7 @@ private static void EmitSourceFile(SourceProductionContext spc, EventSourceClass sb.AppendLine("using System;"); GenType(ec, sb); - spc.AddSource($"{ec.ClassName}.g.cs", SourceText.From(sb.ToString(), Encoding.UTF8)); + context.AddSource($"{ec.ClassName}.g.cs", SourceText.From(sb.ToString(), Encoding.UTF8)); } private static void GenType(EventSourceClass ec, StringBuilder sb) diff --git a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Parser.cs b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Parser.cs index ea1e25f789cf5e..2210157d6842d3 100644 --- a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Parser.cs +++ b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Parser.cs @@ -17,8 +17,8 @@ namespace Generators { public partial class EventSourceGenerator { - private static bool IsSyntaxTargetForGeneration(SyntaxNode node) => - node is ClassDeclarationSyntax x && x.AttributeLists.Count > 0; + private static bool IsSyntaxTargetForGeneration(SyntaxNode node, CancellationToken cancellationToken) => + node is ClassDeclarationSyntax { AttributeLists.Count: > 0 }; private static EventSourceClass? GetSemanticTargetForGeneration(GeneratorSyntaxContext context, CancellationToken cancellationToken) { @@ -107,13 +107,7 @@ private static bool IsSyntaxTargetForGeneration(SyntaxNode node) => result = GenerateGuidFromName(name.ToUpperInvariant()); } - eventSourceClass = new EventSourceClass - { - Namespace = nspace, - ClassName = className, - SourceName = name, - Guid = result - }; + eventSourceClass = new EventSourceClass(nspace, className, name, result); continue; } } diff --git a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.cs b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.cs index 0feecb7e45586c..cebe3a5d32c504 100644 --- a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.cs +++ b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.cs @@ -37,18 +37,12 @@ public void Initialize(IncrementalGeneratorInitializationContext context) { IncrementalValuesProvider eventSourceClasses = context.SyntaxProvider - .CreateSyntaxProvider(static (x, _) => IsSyntaxTargetForGeneration(x), (x, cancellationToken) => GetSemanticTargetForGeneration(x, cancellationToken)) + .CreateSyntaxProvider(IsSyntaxTargetForGeneration, GetSemanticTargetForGeneration) .Where(x => x is not null); - context.RegisterSourceOutput(eventSourceClasses, static (spc, x) => EmitSourceFile(spc, x)); + context.RegisterSourceOutput(eventSourceClasses, EmitSourceFile); } - private sealed class EventSourceClass - { - public string Namespace = string.Empty; - public string ClassName = string.Empty; - public string SourceName = string.Empty; - public Guid Guid = Guid.Empty; - } + private sealed record EventSourceClass(string Namespace, string ClassName, string SourceName, Guid Guid); } } diff --git a/src/libraries/System.Private.CoreLib/gen/System.Private.CoreLib.Generators.csproj b/src/libraries/System.Private.CoreLib/gen/System.Private.CoreLib.Generators.csproj index 6ce771f7124a87..288c65499fbc59 100644 --- a/src/libraries/System.Private.CoreLib/gen/System.Private.CoreLib.Generators.csproj +++ b/src/libraries/System.Private.CoreLib/gen/System.Private.CoreLib.Generators.csproj @@ -12,6 +12,7 @@ + From ac10ce2f9c419b678f76e8c831f952475f97d721 Mon Sep 17 00:00:00 2001 From: Theodore Tsirpanis Date: Tue, 8 Feb 2022 19:51:46 +0200 Subject: [PATCH 7/8] Remove a couple of unused files from the project. --- .../System.Private.CoreLib/gen/EventSourceGenerator.Parser.cs | 1 - .../gen/System.Private.CoreLib.Generators.csproj | 2 -- 2 files changed, 3 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Parser.cs b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Parser.cs index 2210157d6842d3..0ea373c9efb82b 100644 --- a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Parser.cs +++ b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Parser.cs @@ -11,7 +11,6 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.DotnetRuntime.Extensions; namespace Generators { diff --git a/src/libraries/System.Private.CoreLib/gen/System.Private.CoreLib.Generators.csproj b/src/libraries/System.Private.CoreLib/gen/System.Private.CoreLib.Generators.csproj index 288c65499fbc59..2cc2eb0d356af5 100644 --- a/src/libraries/System.Private.CoreLib/gen/System.Private.CoreLib.Generators.csproj +++ b/src/libraries/System.Private.CoreLib/gen/System.Private.CoreLib.Generators.csproj @@ -11,9 +11,7 @@ - - From ee127b9e3fd2a2a356b6bbea1c60181a658d1648 Mon Sep 17 00:00:00 2001 From: Theodore Tsirpanis Date: Thu, 17 Mar 2022 23:51:30 +0200 Subject: [PATCH 8/8] Fix IsExternalInit's path. --- .../gen/System.Private.CoreLib.Generators.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/System.Private.CoreLib/gen/System.Private.CoreLib.Generators.csproj b/src/libraries/System.Private.CoreLib/gen/System.Private.CoreLib.Generators.csproj index 2cc2eb0d356af5..b3274719f5a15a 100644 --- a/src/libraries/System.Private.CoreLib/gen/System.Private.CoreLib.Generators.csproj +++ b/src/libraries/System.Private.CoreLib/gen/System.Private.CoreLib.Generators.csproj @@ -11,7 +11,7 @@ - +