| File: EventSourceGenerator.Emitter.cs | Web Access |
| Project: src\runtime\src\libraries\System.Private.CoreLib\gen\EventSourceGenerator.csproj (EventSourceGenerator) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using System.Text; using System.Threading; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Text; namespace Generators { public partial class EventSourceGenerator { /// <summary>Code for a [GeneratedCode] attribute to put on the top-level generated members.</summary> 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 context, EventSourceClass ec) { if (ec.Diagnostic != null) { context.ReportDiagnostic(ec.Diagnostic); return; } 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)); } 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); if (ec.HasProviderMetadataProperty) { GenerateProviderMetadata(ec.SourceName, sb); } sb.AppendLine($@" }}"); if (!string.IsNullOrWhiteSpace(ec.Namespace)) { sb.AppendLine($@" }}"); } } private static void GenerateConstructor(EventSourceClass ec, StringBuilder sb) { sb.AppendLine($@" private {ec.ClassName}() : base(""{ec.SourceName}"", new Guid({ec.Guid.ToString("x").Replace("{", "").Replace("}", "")})) {{ }}"); } private static void GenerateProviderMetadata(string sourceName, StringBuilder sb) { sb.Append(@" private protected override ReadOnlySpan<byte> ProviderMetadata => ["); 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) { 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')) { throw new ArgumentOutOfRangeException(nameof(name)); } } } }