mirror of
				https://github.com/godotengine/godot.git
				synced 2025-10-30 21:21:10 +00:00 
			
		
		
		
	 ee8e5146a4
			
		
	
	
		ee8e5146a4
		
	
	
	
	
		
			
			The following two bugs were fixed:
- For classes without namespace we were still generating `namespace {`
without a namespace identifier, causing a syntax error.
- For classes with nested namespaces we were generating only the innermost
part of the namespace was being generated, e.g.: for `Foo.Bar` we were
generating `namespace Bar {` instead of `namespace Foo.Bar {`.
This wasn't causing any build error, but because of the wrong namespace
Godot wasn't able to find the class associated with the script.
		
	
			
		
			
				
	
	
		
			89 lines
		
	
	
	
		
			3 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			89 lines
		
	
	
	
		
			3 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| 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);
 | |
| 
 | |
|         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<ClassDeclarationSyntax> 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);
 | |
| 
 | |
|         public static bool HasDisableGeneratorsAttribute(this INamedTypeSymbol symbol)
 | |
|             => symbol.GetAttributes().Any(attr =>
 | |
|                 attr.AttributeClass?.ToString() == GodotClasses.DisableGodotGeneratorsAttr);
 | |
| 
 | |
|         private static SymbolDisplayFormat FullyQualifiedFormatOmitGlobal { get; } =
 | |
|             SymbolDisplayFormat.FullyQualifiedFormat
 | |
|                 .WithGlobalNamespaceStyle(SymbolDisplayGlobalNamespaceStyle.Omitted);
 | |
| 
 | |
|         public static string FullQualifiedName(this INamedTypeSymbol symbol)
 | |
|             => symbol.ToDisplayString(NullableFlowState.NotNull, FullyQualifiedFormatOmitGlobal);
 | |
| 
 | |
|         public static string FullQualifiedName(this INamespaceSymbol namespaceSymbol)
 | |
|             => namespaceSymbol.ToDisplayString(FullyQualifiedFormatOmitGlobal);
 | |
|     }
 | |
| }
 |