using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; namespace Nebula.SourceGenerators; public static class SourceHelper { public static void GenerateAttribute(string attributeName, string usage, IncrementalGeneratorInitializationContext context) { var attributeSourceCode = $@"// namespace SourceGen {{ [System.AttributeUsage(System.AttributeTargets.{usage})] public class {attributeName} : System.Attribute {{ }} }}"; context.RegisterPostInitializationOutput(ctx => ctx.AddSource( $"{attributeName}.g.cs", SourceText.From(attributeSourceCode, Encoding.UTF8))); } public static bool HasAttribute(ISymbol type, string attributeName) { foreach (var attribute in type.GetAttributes()) if (attribute.AttributeClass?.ToDisplayString() == attributeName) return true; return false; } public static (ClassDeclarationSyntax, bool reportAttributeFound) GetClassDeclarationForSourceGen( GeneratorSyntaxContext context, string AttributeName) { var classDeclarationSyntax = (ClassDeclarationSyntax)context.Node; foreach (var attributeListSyntax in classDeclarationSyntax.AttributeLists) foreach (var attributeSyntax in attributeListSyntax.Attributes) { if (context.SemanticModel.GetSymbolInfo(attributeSyntax).Symbol is not IMethodSymbol attributeSymbol) continue; var attributeName = attributeSymbol.ContainingType.ToDisplayString(); if (attributeName == AttributeName) return (classDeclarationSyntax, true); } return (classDeclarationSyntax, false); } }