public OnReadyGetAddition(MemberAttributeSite memberSite) : base(memberSite.AttributeSite.Class) { Member = memberSite.Member; // Handle field name convention: _ prefix with lowercase name. string pathName = Member.Name.TrimStart('_'); pathName = pathName[0].ToString().ToUpperInvariant() + pathName.Substring(1); SuffixlessExportPropertyName = pathName; foreach (var constructorArg in memberSite.AttributeSite.Attribute.ConstructorArguments) { if (constructorArg.Value is string path) { Path = path; } } foreach (var namedArg in memberSite.AttributeSite.Attribute.NamedArguments) { switch (namedArg.Key) { case "Path" when namedArg.Value.Value is string s: Path = s; break; case "Export" when namedArg.Value.Value is bool b: Export = b; break; case "OrNull" when namedArg.Value.Value is bool b: OrNull = b; break; case "Property" when namedArg.Value.Value is string s: Property = s; break; case "NonRecursive" when namedArg.Value.Value is bool b: NonRecursive = b; break; case "Unowned" when namedArg.Value.Value is bool b: Unowned = b; break; } } }
public OnReadyGetNodeAddition(MemberAttributeSite site) : base(site) { }
public void Execute(GeneratorExecutionContext context) { // If this isn't working, run 'dotnet build-server shutdown' first. if (Environment .GetEnvironmentVariable($"Debug{nameof(GodotOnReadySourceGenerator)}") == "true") { Debugger.Launch(); } var receiver = context.SyntaxReceiver as OnReadyReceiver ?? throw new Exception(); INamedTypeSymbol GetSymbolByName(string fullName) => context.Compilation.GetTypeByMetadataName(fullName) ?? throw new Exception($"Can't find {fullName}"); var onReadyGetSymbol = GetSymbolByName("GodotOnReady.Attributes.OnReadyGetAttribute"); var onReadySymbol = GetSymbolByName("GodotOnReady.Attributes.OnReadyAttribute"); var generateDataSelectorEnumSymbol = GetSymbolByName("GodotOnReady.Attributes.GenerateDataSelectorEnumAttribute"); var resourceSymbol = GetSymbolByName("Godot.Resource"); var nodeSymbol = GetSymbolByName("Godot.Node"); List <PartialClassAddition> additions = new(); var classSymbols = receiver.AllClasses .Select(classDecl => { INamedTypeSymbol?classSymbol = context.Compilation .GetSemanticModel(classDecl.SyntaxTree) .GetDeclaredSymbol(classDecl); if (classSymbol is null) { context.ReportDiagnostic( Diagnostic.Create( new DiagnosticDescriptor( "GORSG0001", "Inspection", $"Unable to find declared symbol for {classDecl}. Skipping.", "GORSG.Parsing", DiagnosticSeverity.Warning, true ), classDecl.GetLocation() ) ); } return(classSymbol); }) .Distinct(SymbolEqualityComparer.Default) .OfType <INamedTypeSymbol>(); foreach (var classSymbol in classSymbols) { foreach (var attribute in classSymbol.GetAttributes() .Where(a => Equal(a.AttributeClass, generateDataSelectorEnumSymbol))) { var fields = classSymbol.GetMembers() .OfType <IFieldSymbol>() .Where(f => f.IsReadOnly && f.IsStatic) .ToArray(); additions.Add(new DataSelectorEnumAddition( fields, new AttributeSite(classSymbol, attribute))); } var members = Enumerable .Concat( classSymbol.GetMembers().OfType <IPropertySymbol>().Select(MemberSymbol.Create), classSymbol.GetMembers().OfType <IFieldSymbol>().Select(MemberSymbol.Create)) .ToArray(); foreach (var member in members) { foreach (var attribute in member.Symbol .GetAttributes() .Where(a => Equal(a.AttributeClass, onReadyGetSymbol))) { var site = new MemberAttributeSite( member, new AttributeSite(classSymbol, attribute)); if (site.AttributeSite.Attribute.NamedArguments.Any( a => a.Key == "Property" && a.Value.Value is string { Length: > 0 }))
public OnReadyGetResourceAddition(MemberAttributeSite site) : base(site) { }
public InjectAncestorValueAddition(MemberAttributeSite memberSite) : base(memberSite.AttributeSite.Class) { Member = memberSite.Member; _nodeType = (INamedTypeSymbol)Member.Type; _nodeName = _nodeType.Name; var args = memberSite.AttributeSite.Attribute.ConstructorArguments; if (args.Length > 0) { if (args[0].Value is INamedTypeSymbol s) { _nodeType = s; _nodeName = _nodeType.Name; } } if (args.Length > 1) { if (args[1].Value is string s) { _nodeName = s; } } // We don't want the node, we want a property or field of the node with a specific type. if (!Member.Type.Equals(_nodeType, SymbolEqualityComparer.Default)) { var matches = MemberSymbol.CreateAll(_nodeType) .Where(s => // Ignore backing fields. !s.Symbol.IsImplicitlyDeclared && s.Type.IsOfBaseType(Member.Type)) .ToArray(); if (matches.Length == 0) { string issue = $"No field or property of type \"{Member.Type.ToFullDisplayString()}\" " + $"found in injection source \"{_nodeType.ToFullDisplayString()}\". " + "Expected exactly one"; Diagnostics.Add( Diagnostic.Create( new DiagnosticDescriptor( "GORSG0004", "Inspection", issue, "GORSG.Parsing", DiagnosticSeverity.Error, true ), Member.Symbol.Locations.FirstOrDefault() ) ); } else if (matches.Length > 1) { string issue = $"Multiple members of type \"{Member.Type.ToFullDisplayString()}\" " + $"found in injection source {_nodeType.ToFullDisplayString()}, " + "but expected exactly one. Found: " + string.Join(", ", matches.Select(m => m.Name)); Diagnostics.Add( Diagnostic.Create( new DiagnosticDescriptor( "GORSG0005", "Inspection", issue, "GORSG.Parsing", DiagnosticSeverity.Error, true ), Member.Symbol.Locations.FirstOrDefault() ) ); } else { _sourceMember = matches[0]; } } }