using System.Collections.Generic; using System.Linq; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; namespace MfGames.Nitride.Generators; public abstract class ClassAttributeSyntaxReceiverBase : ISyntaxReceiver { private readonly string attributeName; private readonly GeneratorInitializationContext context; public ClassAttributeSyntaxReceiverBase( GeneratorInitializationContext context, string attributeName) { this.context = context; this.attributeName = attributeName; this.ReferenceList = new List(); this.Messages = new List(); } /// /// Gets or sets a value indicating whether we should debug parsing attributes. /// public bool DebugAttributes { get; set; } public List Messages { get; } /// /// Gets or sets the name of the analyzed namespace. /// public string? Namespace { get; private set; } public List ReferenceList { get; } public List UsingDirectiveList { get; set; } = new(); public void OnVisitSyntaxNode(SyntaxNode syntaxNode) { // Check for namespaces. switch (syntaxNode) { case CompilationUnitSyntax: // Reset everything. this.Namespace = null!; this.UsingDirectiveList = new List(); break; case NamespaceDeclarationSyntax syntax: this.Namespace = syntax.Name.ToString(); return; case FileScopedNamespaceDeclarationSyntax syntax: this.Namespace = syntax.Name.ToString(); return; case UsingDirectiveSyntax syntax: this.UsingDirectiveList.Add(syntax); return; case ClassDeclarationSyntax: break; default: return; } // We only care about class declarations. if (syntaxNode is not ClassDeclarationSyntax cds) { return; } // See if the class has our set properties attribute. var attributes = cds.AttributeLists .AsEnumerable() .SelectMany(x => x.Attributes) .Select(x => x.Name.ToString()) .ToList(); bool found = attributes .Any( x => x == this.attributeName || x == $"{this.attributeName}Attribute"); if (this.DebugAttributes) { this.Messages.Add( string.Format( "Parsing {0} found? {1} from attributes [{2}]", cds.Identifier, found, string.Join(", ", attributes))); } if (found) { this.ReferenceList.Add( new ClassAttributeReference { Namespace = this.Namespace!, UsingDirectiveList = this.UsingDirectiveList, ClassDeclaration = cds, }); } } }