1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
| using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using System; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Threading; using System.Xml.Linq;
namespace SourceGenerator2.UseAttribute { [Generator(LanguageNames.CSharp)] public class SourceGenerator2UseAttribute : IIncrementalGenerator { public void Initialize(IncrementalGeneratorInitializationContext context) { #region context.RegisterSourceOutput( context.SyntaxProvider .ForAttributeWithMetadataName("SourceGenerator2.SayHello2Attribute", NodePredicate, static (gasc, _) => gasc switch { { TargetNode: MethodDeclarationSyntax node, TargetSymbol: IMethodSymbol { Name: var methodName, TypeParameters: [], Parameters: [{ Type.SpecialType: SpecialType.System_String, Name: var parameterName }], ReturnsVoid: true, IsStatic: true, ContainingType: { Name: var typeName, ContainingNamespace: var @namespace, TypeKind: var typeKind and (TypeKind.Class or TypeKind.Struct or TypeKind.Interface) } } } => new GatheredData { MethodName = methodName, ParameterName = parameterName, TypeName = typeName, Namespace = @namespace, TypeKind = typeKind, Node = node }, _ => null } ).Collect(),
(spc, data) => { foreach (var item in data) { if (item is null) { continue; } var namespaceName = item.Namespace.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); namespaceName = namespaceName["global::".Length..]; var typeKindString = item.TypeKind switch { TypeKind.Class => "class", TypeKind.Struct => "struct", TypeKind.Interface => "interface", _ => throw new NotImplementedException() };
spc.AddSource( $"{item.TypeName}.g.cs", $$""" // <auto-generated/> #nullable enable namespace {{namespaceName}}; partial {{typeKindString}} {{item.TypeName}} { {{item.Node.Modifiers}} void {{item.MethodName}}(string {{item.ParameterName}}) => global::System.Console.WriteLine($"Hello, {{{item.ParameterName}}}!"); } """ ); } }
); #endregion } public bool NodePredicate(SyntaxNode node, CancellationToken token) => node is MethodDeclarationSyntax { Modifiers: var modifiers and not [], Parent: TypeDeclarationSyntax { Modifiers: var typemodifiers and not [] } } && modifiers.Any(SyntaxKind.PartialKeyword) && typemodifiers.Any(SyntaxKind.PartialKeyword); } }
file class GatheredData { public string MethodName { set; get; } public string ParameterName { set; get; } public string TypeName { set; get; } public INamespaceSymbol Namespace { set; get; } public TypeKind TypeKind { set; get; } public MethodDeclarationSyntax Node { set; get; } }
|