|
// 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)
{
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);
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(new Guid({ec.Guid.ToString("x").Replace("{", "").Replace("}", "")}), ""{ec.SourceName}"") {{ }}");
}
private static void GenerateProviderMetadata(string sourceName, StringBuilder sb)
{
sb.Append(@"
private protected override ReadOnlySpan<byte> 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)
{
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));
}
}
}
}
|