forked from dotnet/runtime
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
EventSourceGenerator for Guid+Name .ctor and Metadata (dotnet#45699)
- Loading branch information
Showing
17 changed files
with
618 additions
and
42 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
109 changes: 109 additions & 0 deletions
109
src/libraries/System.Private.CoreLib/generators/EventSourceGenerator.Emitter.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
// 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 | ||
{ | ||
private 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) | ||
{ | ||
foreach (EventSourceClass? ec in eventSources) | ||
{ | ||
if (cancellationToken.IsCancellationRequested) | ||
{ | ||
// stop any additional work | ||
break; | ||
} | ||
|
||
_builder.AppendLine("using System;"); | ||
GenType(ec); | ||
|
||
_context.AddSource($"{ec.ClassName}.Generated", SourceText.From(_builder.ToString(), Encoding.UTF8)); | ||
|
||
_builder.Clear(); | ||
} | ||
} | ||
|
||
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 void GenerateConstructor(EventSourceClass ec) | ||
{ | ||
_builder.AppendLine($@" | ||
private {ec.ClassName}() : base(new Guid({ec.Guid.ToString("x").Replace("{", "").Replace("}", "")}), ""{ec.SourceName}"") {{ }}"); | ||
} | ||
|
||
private void GenerateProviderMetadata(string sourceName) | ||
{ | ||
_builder.Append(@" | ||
private protected override ReadOnlySpan<byte> ProviderMetadata => new byte[] { "); | ||
|
||
byte[] metadataBytes = MetadataForString(sourceName); | ||
foreach (byte b in metadataBytes) | ||
{ | ||
_builder.Append($"0x{b:x}, "); | ||
} | ||
|
||
_builder.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)); | ||
} | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.