-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Polyfill the incremental generator ForAttributeWithMetadataName from roslyn (for EventSourceGeneration). #71662
Changes from 3 commits
498b5e6
6cade39
f8b212b
2ed84a2
b2847be
e09862d
4ce9f76
c2a0af8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,116 +4,90 @@ | |
using System; | ||
using System.Collections.Generic; | ||
using System.Collections.Immutable; | ||
using System.Linq; | ||
using System.Security.Cryptography; | ||
using System.Text; | ||
using System.Threading; | ||
using Microsoft.CodeAnalysis; | ||
using Microsoft.CodeAnalysis.CSharp; | ||
using Microsoft.CodeAnalysis.CSharp.Syntax; | ||
using Microsoft.CodeAnalysis.DotnetRuntime.Extensions; | ||
|
||
namespace Generators | ||
{ | ||
public partial class EventSourceGenerator | ||
{ | ||
private static bool IsSyntaxTargetForGeneration(SyntaxNode node, CancellationToken cancellationToken) => | ||
node is ClassDeclarationSyntax { AttributeLists.Count: > 0 }; | ||
|
||
private static EventSourceClass? GetSemanticTargetForGeneration(GeneratorSyntaxContext context, CancellationToken cancellationToken) | ||
private static EventSourceClass? GetSemanticTargetForGeneration(GeneratorAttributeSyntaxContext 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; | ||
var classDef = (ClassDeclarationSyntax)context.TargetNode; | ||
|
||
EventSourceClass? eventSourceClass = null; | ||
|
||
bool autoGenerate = false; | ||
foreach (AttributeListSyntax cal in classDef.AttributeLists) | ||
foreach (AttributeData attribute in context.TargetSymbol.GetAttributes()) | ||
{ | ||
foreach (AttributeSyntax ca in cal.Attributes) | ||
{ | ||
if (sm.GetSymbolInfo(ca, cancellationToken).Symbol is not IMethodSymbol caSymbol) | ||
{ | ||
// badly formed attribute definition, or not the right attribute | ||
continue; | ||
} | ||
|
||
string attributeFullName = caSymbol.ContainingType.ToDisplayString(); | ||
if (attribute.AttributeClass is null) | ||
continue; | ||
|
||
if (attributeFullName.Equals(EventSourceAutoGenerateAttribute, StringComparison.Ordinal)) | ||
NamespaceDeclarationSyntax? ns = classDef.Parent as NamespaceDeclarationSyntax; | ||
if (ns is null) | ||
{ | ||
if (classDef.Parent is not CompilationUnitSyntax) | ||
{ | ||
autoGenerate = true; | ||
// since this generator doesn't know how to generate a nested type... | ||
continue; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we required having EventSourceAutoGenerateAttribute before. otherwise, autogenerate would not be true, and we'd bail out below. |
||
} | ||
} | ||
|
||
if (!attributeFullName.Equals(EventSourceAttribute, StringComparison.Ordinal)) | ||
{ | ||
continue; | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the code below would only execute if we had EventSourceAttribute, so that's what we maintain below. |
||
if (attribute.AttributeClass.Name != "EventSourceAttribute" && | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. indeed!
CyrusNajmabadi marked this conversation as resolved.
Show resolved
Hide resolved
|
||
attribute.AttributeClass.ToDisplayString() != EventSourceAttribute) | ||
{ | ||
continue; | ||
} | ||
|
||
string nspace = string.Empty; | ||
NamespaceDeclarationSyntax? ns = classDef.Parent as NamespaceDeclarationSyntax; | ||
if (ns is null) | ||
string nspace = string.Empty; | ||
if (ns is not null) | ||
{ | ||
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.ValueText; | ||
string name = className; | ||
string guid = ""; | ||
|
||
SeparatedSyntaxList<AttributeArgumentSyntax>? 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; | ||
} | ||
} | ||
} | ||
ImmutableArray<KeyValuePair<string, TypedConstant>> args = attribute.NamedArguments; | ||
foreach (KeyValuePair<string, TypedConstant> arg in args) | ||
{ | ||
string argName = arg.Key; | ||
string value = arg.Value.Value?.ToString(); | ||
|
||
if (!Guid.TryParse(guid, out Guid result)) | ||
switch (argName) | ||
{ | ||
result = GenerateGuidFromName(name.ToUpperInvariant()); | ||
case "Guid": | ||
guid = value; | ||
break; | ||
case "Name": | ||
name = value; | ||
break; | ||
} | ||
} | ||
|
||
eventSourceClass = new EventSourceClass(nspace, className, name, result); | ||
continue; | ||
if (!Guid.TryParse(guid, out Guid result)) | ||
{ | ||
result = GenerateGuidFromName(name.ToUpperInvariant()); | ||
} | ||
} | ||
|
||
if (!autoGenerate) | ||
{ | ||
return null; | ||
eventSourceClass = new EventSourceClass(nspace, className, name, result); | ||
continue; | ||
} | ||
|
||
return eventSourceClass; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we don't need to check for EventSourceAutoGenerateAttribute. we wouldn't have gotten here unless we had that attribute on the class we're examining.