using System; using System.Linq; using System.Text; using GFramework.SourceGenerators.Abstractions.rule; using GFramework.SourceGenerators.Common.generator; using GFramework.SourceGenerators.diagnostics; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; namespace GFramework.SourceGenerators.rule; [Generator] public sealed class ContextAwareGenerator : AttributeClassGeneratorBase { /// /// 使用强类型 Attribute,替代字符串 /// protected override Type AttributeType => typeof(ContextAwareAttribute); /// /// 仅用于 Syntax 粗筛选 /// protected override string AttributeShortNameWithoutSuffix => "ContextAware"; /// /// 额外语义校验:必须实现 IContextAware /// protected override bool ValidateSymbol( SourceProductionContext context, ClassDeclarationSyntax syntax, INamedTypeSymbol symbol, AttributeData attr) { if (!symbol.AllInterfaces.Any(i => i.ToDisplayString() == typeof(IContextAware).FullName)) { context.ReportDiagnostic(Diagnostic.Create( ContextAwareDiagnostic.ClassMustImplementIContextAware, syntax.Identifier.GetLocation(), symbol.Name)); return false; } return true; } /// /// 生成源码 /// protected override string Generate( INamedTypeSymbol symbol, AttributeData attr) { var ns = symbol.ContainingNamespace.IsGlobalNamespace ? null : symbol.ContainingNamespace.ToDisplayString(); var sb = new StringBuilder(); sb.AppendLine("// "); sb.AppendLine("#nullable enable"); if (ns is not null) { sb.AppendLine($"namespace {ns};"); sb.AppendLine(); } sb.AppendLine($"partial class {symbol.Name}"); sb.AppendLine("{"); sb.AppendLine( " protected GFramework.Core.architecture.IArchitectureContext Context { get; private set; } = null!;"); sb.AppendLine(" void GFramework.Core.rule.IContextAware.SetContext("); sb.AppendLine(" GFramework.Core.architecture.IArchitectureContext context)"); sb.AppendLine(" {"); sb.AppendLine(" Context = context;"); sb.AppendLine(" }"); sb.AppendLine("}"); return sb.ToString().TrimEnd(); } /// /// 自定义生成文件名 /// protected override string GetHintName(INamedTypeSymbol symbol) => $"{symbol.Name}.ContextAware.g.cs"; }