-
Notifications
You must be signed in to change notification settings - Fork 4.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add source generator for system event mapping/constants (#20873)
* Add source generator for system event mapping/constants * PR FB * PR FB * Missing files * docsettings * remove code * Fix build * changelog * More fixing * Use correct property * DocSettings
- Loading branch information
1 parent
98311bc
commit ab7400c
Showing
110 changed files
with
1,173 additions
and
1,002 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
11 changes: 11 additions & 0 deletions
11
sdk/eventgrid/Azure.Messaging.EventGrid/EventGridSourceGenerator/Directory.Build.props
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,11 @@ | ||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||
<!-- | ||
Add any shared properties you want for the projects under this package directory that need to be set before the auto imported Directory.Build.props | ||
--> | ||
<PropertyGroup> | ||
<ImportRepoCommonSettings>true</ImportRepoCommonSettings> | ||
<SupportsNetStandard20>true</SupportsNetStandard20> | ||
<IsShippingLibrary>false</IsShippingLibrary> | ||
</PropertyGroup> | ||
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory).., Directory.Build.props))\Directory.Build.props" /> | ||
</Project> |
131 changes: 131 additions & 0 deletions
131
...ntgrid/Azure.Messaging.EventGrid/EventGridSourceGenerator/src/EventGridSourceGenerator.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,131 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
using System.Diagnostics; | ||
using System.Linq; | ||
using System.Text; | ||
using Microsoft.CodeAnalysis; | ||
using Microsoft.CodeAnalysis.CSharp; | ||
using Microsoft.CodeAnalysis.Text; | ||
|
||
namespace EventGridSourceGenerator | ||
{ | ||
/// <summary> | ||
/// This class generates the SystemEventNames constant values as well as the SystemEventExtensions which contains a mapping | ||
/// from constant values to deserialization method for each system event. | ||
/// </summary> | ||
[Generator] | ||
internal class EventGridSourceGenerator : ISourceGenerator | ||
{ | ||
private SourceVisitor _visitor; | ||
private const string Indent = " "; | ||
|
||
public void Execute(GeneratorExecutionContext context) | ||
{ | ||
_visitor = new SourceVisitor(); | ||
var root = context.Compilation.GetSymbolsWithName( | ||
"SystemEvents", | ||
SymbolFilter.Namespace) | ||
.Single(); | ||
_visitor.Visit(root); | ||
|
||
context.AddSource("SystemEventNames.cs", SourceText.From(ConstructSystemEventNames(), Encoding.UTF8)); | ||
context.AddSource("SystemEventExtensions.cs", SourceText.From(ConstructSystemEventExtensions(), Encoding.UTF8)); | ||
} | ||
|
||
public void Initialize(GeneratorInitializationContext context) | ||
{ | ||
// Uncomment to debug | ||
//if (!Debugger.IsAttached) | ||
//{ | ||
// Debugger.Launch(); | ||
//} | ||
} | ||
|
||
private string ConstructSystemEventNames() | ||
{ | ||
var sourceBuilder = new StringBuilder( | ||
@"// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
// <auto-generated/> | ||
using Azure.Messaging.EventGrid.SystemEvents; | ||
namespace Azure.Messaging.EventGrid | ||
{ | ||
/// <summary> | ||
/// Represents the names of the various event types for the system events published to | ||
/// Azure Event Grid. | ||
/// </summary> | ||
public static class SystemEventNames | ||
{ | ||
"); | ||
for (int i = 0; i < _visitor.SystemEvents.Count; i++) | ||
{ | ||
if (i > 0) | ||
{ | ||
sourceBuilder.AppendLine(); | ||
} | ||
SystemEventNode sysEvent = _visitor.SystemEvents[i]; | ||
|
||
// Add the ref docs for each constant | ||
sourceBuilder.AppendLine($"{Indent}{Indent}/// <summary>"); | ||
sourceBuilder.AppendLine($"{Indent}{Indent}/// The value of the Event Type stored in <see cref=\"EventGridEvent.EventType\"/> and <see cref=\"CloudEvent.Type\"/> "); | ||
sourceBuilder.AppendLine($"{Indent}{Indent}/// for the <see cref=\"{sysEvent.EventName}\"/> system event."); | ||
sourceBuilder.AppendLine($"{Indent}{Indent}/// </summary>"); | ||
|
||
// Add the constant | ||
sourceBuilder.AppendLine($"{Indent}{Indent}public const string {sysEvent.EventConstantName} = {sysEvent.EventType};"); | ||
} | ||
|
||
sourceBuilder.Append($@"{Indent}}} | ||
}}"); | ||
return sourceBuilder.ToString(); | ||
} | ||
|
||
private string ConstructSystemEventExtensions() | ||
{ | ||
var sourceBuilder = new StringBuilder( | ||
@"// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
// <auto-generated/> | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Text.Json; | ||
using Azure.Messaging.EventGrid.SystemEvents; | ||
namespace Azure.Messaging.EventGrid | ||
{ | ||
internal class SystemEventExtensions | ||
{ | ||
public static object AsSystemEventData(string eventType, JsonElement data) | ||
{ | ||
if (s_systemEventDeserializers.TryGetValue(eventType, out Func<JsonElement, object> systemDeserializationFunction)) | ||
{ | ||
return systemDeserializationFunction(data); | ||
} | ||
else | ||
{ | ||
return null; | ||
} | ||
} | ||
internal static readonly IReadOnlyDictionary<string, Func<JsonElement, object>> s_systemEventDeserializers = new Dictionary<string, Func<JsonElement, object>>(StringComparer.OrdinalIgnoreCase) | ||
{ | ||
"); | ||
foreach (SystemEventNode sysEvent in _visitor.SystemEvents) | ||
{ | ||
// Add each an entry for each system event to the dictionary containing a mapping from constant name to deserialization method. | ||
sourceBuilder.AppendLine( | ||
$"{Indent}{Indent}{Indent}{{ SystemEventNames.{sysEvent.EventConstantName}, {sysEvent.EventName}.{sysEvent.DeserializeMethod} }},"); | ||
} | ||
sourceBuilder.Append($@"{Indent}{Indent}}}; | ||
{Indent}}} | ||
}}"); | ||
return sourceBuilder.ToString(); | ||
} | ||
} | ||
} |
12 changes: 12 additions & 0 deletions
12
...id/Azure.Messaging.EventGrid/EventGridSourceGenerator/src/EventGridSourceGenerator.csproj
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,12 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>netstandard2.0</TargetFramework> | ||
<LangVersion>latest</LangVersion> | ||
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles> | ||
</PropertyGroup> | ||
<ItemGroup> | ||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" PrivateAssets="all" /> | ||
</ItemGroup> | ||
|
||
</Project> |
56 changes: 56 additions & 0 deletions
56
sdk/eventgrid/Azure.Messaging.EventGrid/EventGridSourceGenerator/src/SourceVisitor.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,56 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text.RegularExpressions; | ||
using System.Xml; | ||
using Microsoft.CodeAnalysis; | ||
using Microsoft.CodeAnalysis.CSharp.Syntax; | ||
|
||
namespace EventGridSourceGenerator | ||
{ | ||
internal class SourceVisitor : SymbolVisitor | ||
{ | ||
public List<SystemEventNode> SystemEvents { get; } = new(); | ||
|
||
public override void VisitNamespace(INamespaceSymbol symbol) | ||
{ | ||
foreach (var childSymbol in symbol.GetMembers()) | ||
{ | ||
childSymbol.Accept(this); | ||
} | ||
} | ||
|
||
public override void VisitNamedType(INamedTypeSymbol symbol) | ||
{ | ||
if (symbol.Name.EndsWith("EventData")) | ||
{ | ||
string type = null; | ||
XmlDocument xmlDoc = new(); | ||
xmlDoc.LoadXml(symbol.GetDocumentationCommentXml()); | ||
var xmlNode = xmlDoc.SelectSingleNode("member/summary"); | ||
var match = Regex.Match(xmlNode.InnerText, "[a-zA-Z]+\\.[a-zA-Z]+\\.[a-zA-Z]+"); | ||
if (!match.Success) | ||
{ | ||
// We expect some EventData to not have event types if they are base types, | ||
// e.g. ContainerRegistryEventData | ||
return; | ||
} | ||
|
||
type = $@"""{match.Value}"""; | ||
SystemEvents.Add( | ||
new SystemEventNode() | ||
{ | ||
EventName = symbol.Name, | ||
EventType = | ||
// temporary workaround until https://github.com/Azure/azure-rest-api-specs/pull/14261/ is merged | ||
type == @"""Microsoft.ServiceBus.DeadletterMessagesAvailableWithNoListenersEvent""" ? | ||
@"""Microsoft.ServiceBus.DeadletterMessagesAvailableWithNoListener""" | ||
: type, | ||
DeserializeMethod = symbol.MemberNames.Single(m => m.StartsWith("Deserialize")) | ||
}); | ||
} | ||
} | ||
} | ||
} |
29 changes: 29 additions & 0 deletions
29
sdk/eventgrid/Azure.Messaging.EventGrid/EventGridSourceGenerator/src/SystemEventNode.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,29 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
namespace EventGridSourceGenerator | ||
{ | ||
internal class SystemEventNode | ||
{ | ||
public string EventName { get; set; } | ||
|
||
public string EventConstantName | ||
{ | ||
get | ||
{ | ||
// special case a few events that don't follow the pattern | ||
return EventName switch | ||
{ | ||
"ServiceBusDeadletterMessagesAvailableWithNoListenersEventData" => "ServiceBusDeadletterMessagesAvailableWithNoListener", | ||
"SubscriptionDeletedEventData" => "EventGridSubscriptionDeleted", | ||
"SubscriptionValidationEventData" => "EventGridSubscriptionValidation", | ||
_ => EventName?.Replace("EventData", ""), | ||
}; | ||
} | ||
} | ||
|
||
public string EventType { get; set; } | ||
|
||
public string DeserializeMethod { get; set; } | ||
} | ||
} |
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
Oops, something went wrong.