using System; using System.Collections.Generic; using System.Linq; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; namespace Godot.SourceGenerators { static class ExtensionMethods { public static bool TryGetGlobalAnalyzerProperty( this GeneratorExecutionContext context, string property, out string? value ) => context.AnalyzerConfigOptions.GlobalOptions .TryGetValue("build_property." + property, out value); public static bool AreGodotSourceGeneratorsDisabled(this GeneratorExecutionContext context) => context.TryGetGlobalAnalyzerProperty("GodotSourceGenerators", out string? toggle) && toggle != null && toggle.Equals("disabled", StringComparison.OrdinalIgnoreCase); private static bool InheritsFrom(this INamedTypeSymbol? symbol, string baseName) { if (symbol == null) return false; while (true) { if (symbol.ToString() == baseName) { return true; } if (symbol.BaseType != null) { symbol = symbol.BaseType; continue; } break; } return false; } private static bool IsGodotScriptClass( this ClassDeclarationSyntax cds, Compilation compilation, out INamedTypeSymbol? symbol ) { var sm = compilation.GetSemanticModel(cds.SyntaxTree); var classTypeSymbol = sm.GetDeclaredSymbol(cds); if (classTypeSymbol?.BaseType == null || !classTypeSymbol.BaseType.InheritsFrom(GodotClasses.Object)) { symbol = null; return false; } symbol = classTypeSymbol; return true; } public static IEnumerable<(ClassDeclarationSyntax cds, INamedTypeSymbol symbol)> SelectGodotScriptClasses( this IEnumerable source, Compilation compilation ) { foreach (var cds in source) { if (cds.IsGodotScriptClass(compilation, out var symbol)) yield return (cds, symbol!); } } public static bool IsPartial(this ClassDeclarationSyntax cds) => cds.Modifiers.Any(SyntaxKind.PartialKeyword); private static SymbolDisplayFormat FullyQualifiedFormatOmitGlobal { get; } = SymbolDisplayFormat.FullyQualifiedFormat .WithGlobalNamespaceStyle(SymbolDisplayGlobalNamespaceStyle.Omitted); public static string FullQualifiedName(this ITypeSymbol symbol) => symbol.ToDisplayString(NullableFlowState.NotNull, FullyQualifiedFormatOmitGlobal); public static string FullQualifiedName(this INamespaceSymbol namespaceSymbol) => namespaceSymbol.ToDisplayString(FullyQualifiedFormatOmitGlobal); } }