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);
|
|
}
|
|
}
|