diff options
Diffstat (limited to 'modules/mono/editor')
20 files changed, 336 insertions, 114 deletions
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ExportedFields.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ExportedFields.cs index ac8d6473a6..9a46b7d164 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ExportedFields.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ExportedFields.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; #pragma warning disable CS0169 @@ -83,6 +84,10 @@ namespace Godot.SourceGenerators.Sample [Export] private StringName[] field_StringNameArray = { "foo", "bar" }; [Export] private NodePath[] field_NodePathArray = { "foo", "bar" }; [Export] private RID[] field_RIDArray = { default, default, default }; + // Note we use Array and not System.Array. This tests the generated namespace qualification. + [Export] private Int32[] field_empty_Int32Array = Array.Empty<Int32>(); + // Note we use List and not System.Collections.Generic. + [Export] private int[] field_array_from_list = new List<int>(Array.Empty<int>()).ToArray(); // Variant [Export] private Variant field_Variant = "foo"; diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ExportedProperties.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ExportedProperties.cs index 3020cfbc50..eb83833b40 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ExportedProperties.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ExportedProperties.cs @@ -12,6 +12,95 @@ namespace Godot.SourceGenerators.Sample [SuppressMessage("ReSharper", "InconsistentNaming")] public partial class ExportedProperties : Godot.Object { + // Do not generate default value + private String _notGenerate_Property_String = new string("not generate"); + [Export] + public String NotGenerate_Complex_Lamda_Property + { + get => _notGenerate_Property_String + Convert.ToInt32("1"); + set => _notGenerate_Property_String = value; + } + + [Export] + public String NotGenerate_Lamda_NoField_Property + { + get => new string("not generate"); + set => _notGenerate_Property_String = value; + } + + [Export] + public String NotGenerate_Complex_Return_Property + { + get + { + return _notGenerate_Property_String + Convert.ToInt32("1"); + } + set + { + _notGenerate_Property_String = value; + } + } + + private int _notGenerate_Property_Int = 1; + [Export] + public string NotGenerate_Returns_Property + { + get + { + if (_notGenerate_Property_Int == 1) + { + return "a"; + } + else + { + return "b"; + } + } + set + { + _notGenerate_Property_Int = value == "a" ? 1 : 2; + } + } + + // Full Property + private String _fullProperty_String = "FullProperty_String"; + [Export] + public String FullProperty_String + { + get + { + return _fullProperty_String; + } + set + { + _fullProperty_String = value; + } + } + + private String _fullProperty_String_Complex = new string("FullProperty_String_Complex") + Convert.ToInt32("1"); + [Export] + public String FullProperty_String_Complex + { + get + { + return _fullProperty_String_Complex; + } + set + { + _fullProperty_String_Complex = value; + } + } + + // Lamda Property + private String _lamdaProperty_String = "LamdaProperty_String"; + [Export] + public String LamdaProperty_String + { + get => _lamdaProperty_String; + set => _lamdaProperty_String = value; + } + + // Auto Property [Export] private Boolean property_Boolean { get; set; } = true; [Export] private Char property_Char { get; set; } = 'f'; [Export] private SByte property_SByte { get; set; } = 10; diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/MoreExportedFields.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/MoreExportedFields.cs new file mode 100644 index 0000000000..a6c8e52667 --- /dev/null +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/MoreExportedFields.cs @@ -0,0 +1,19 @@ +using System; +using System.Diagnostics.CodeAnalysis; + +#pragma warning disable CS0169 +#pragma warning disable CS0414 + +namespace Godot.SourceGenerators.Sample +{ + [SuppressMessage("ReSharper", "BuiltInTypeReferenceStyle")] + [SuppressMessage("ReSharper", "RedundantNameQualifier")] + [SuppressMessage("ReSharper", "ArrangeObjectCreationWhenTypeEvident")] + [SuppressMessage("ReSharper", "InconsistentNaming")] + // We split the definition of ExportedFields to verify properties work across multiple files. + public partial class ExportedFields : Godot.Object + { + // Note we use Array and not System.Array. This tests the generated namespace qualification. + [Export] private Int64[] field_empty_Int64Array = Array.Empty<Int64>(); + } +} diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Common.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Common.cs index e28788ec0b..4eed2d7b7b 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Common.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Common.cs @@ -14,7 +14,7 @@ namespace Godot.SourceGenerators { string message = "Missing partial modifier on declaration of type '" + - $"{symbol.FullQualifiedName()}' which is a subclass of '{GodotClasses.Object}'"; + $"{symbol.FullQualifiedNameOmitGlobal()}' which is a subclass of '{GodotClasses.Object}'"; string description = $"{message}. Subclasses of '{GodotClasses.Object}' " + "must be declared with the partial modifier."; @@ -41,7 +41,7 @@ namespace Godot.SourceGenerators .GetDeclaredSymbol(outerTypeDeclSyntax); string fullQualifiedName = outerSymbol is INamedTypeSymbol namedTypeSymbol ? - namedTypeSymbol.FullQualifiedName() : + namedTypeSymbol.FullQualifiedNameOmitGlobal() : "type not found"; string message = diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ExtensionMethods.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ExtensionMethods.cs index 8de12de23b..7008fb638f 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ExtensionMethods.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ExtensionMethods.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; @@ -148,22 +149,73 @@ namespace Godot.SourceGenerators }; } + public static string NameWithTypeParameters(this INamedTypeSymbol symbol) + { + return symbol.IsGenericType ? + string.Concat(symbol.Name, "<", string.Join(", ", symbol.TypeParameters), ">") : + symbol.Name; + } + private static SymbolDisplayFormat FullyQualifiedFormatOmitGlobal { get; } = SymbolDisplayFormat.FullyQualifiedFormat .WithGlobalNamespaceStyle(SymbolDisplayGlobalNamespaceStyle.Omitted); - public static string FullQualifiedName(this ITypeSymbol symbol) + private static SymbolDisplayFormat FullyQualifiedFormatIncludeGlobal { get; } = + SymbolDisplayFormat.FullyQualifiedFormat + .WithGlobalNamespaceStyle(SymbolDisplayGlobalNamespaceStyle.Included); + + public static string FullQualifiedNameOmitGlobal(this ITypeSymbol symbol) => symbol.ToDisplayString(NullableFlowState.NotNull, FullyQualifiedFormatOmitGlobal); - public static string NameWithTypeParameters(this INamedTypeSymbol symbol) + public static string FullQualifiedNameOmitGlobal(this INamespaceSymbol namespaceSymbol) + => namespaceSymbol.ToDisplayString(FullyQualifiedFormatOmitGlobal); + + public static string FullQualifiedNameIncludeGlobal(this ITypeSymbol symbol) + => symbol.ToDisplayString(NullableFlowState.NotNull, FullyQualifiedFormatIncludeGlobal); + + public static string FullQualifiedNameIncludeGlobal(this INamespaceSymbol namespaceSymbol) + => namespaceSymbol.ToDisplayString(FullyQualifiedFormatIncludeGlobal); + + public static string FullQualifiedSyntax(this SyntaxNode node, SemanticModel sm) { - return symbol.IsGenericType ? - string.Concat(symbol.Name, "<", string.Join(", ", symbol.TypeParameters), ">") : - symbol.Name; + StringBuilder sb = new(); + FullQualifiedSyntax(node, sm, sb, true); + return sb.ToString(); } - public static string FullQualifiedName(this INamespaceSymbol namespaceSymbol) - => namespaceSymbol.ToDisplayString(FullyQualifiedFormatOmitGlobal); + private static void FullQualifiedSyntax(SyntaxNode node, SemanticModel sm, StringBuilder sb, bool isFirstNode) + { + if (node is NameSyntax ns && isFirstNode) + { + SymbolInfo nameInfo = sm.GetSymbolInfo(ns); + sb.Append(nameInfo.Symbol?.ToDisplayString(FullyQualifiedFormatIncludeGlobal) ?? ns.ToString()); + return; + } + + bool innerIsFirstNode = true; + foreach (var child in node.ChildNodesAndTokens()) + { + if (child.HasLeadingTrivia) + { + sb.Append(child.GetLeadingTrivia()); + } + + if (child.IsNode) + { + FullQualifiedSyntax(child.AsNode()!, sm, sb, isFirstNode: innerIsFirstNode); + innerIsFirstNode = false; + } + else + { + sb.Append(child); + } + + if (child.HasTrailingTrivia) + { + sb.Append(child.GetTrailingTrivia()); + } + } + } public static string SanitizeQualifiedNameForUniqueHint(this string qualifiedName) => qualifiedName diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotEnums.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotEnums.cs index 1a25d684a0..88c0e71155 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotEnums.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotEnums.cs @@ -71,29 +71,29 @@ namespace Godot.SourceGenerators Expression = 19, PlaceholderText = 20, ColorNoAlpha = 21, - ImageCompressLossy = 22, - ImageCompressLossless = 23, - ObjectId = 24, - TypeString = 25, - NodePathToEditedNode = 26, - MethodOfVariantType = 27, - MethodOfBaseType = 28, - MethodOfInstance = 29, - MethodOfScript = 30, - PropertyOfVariantType = 31, - PropertyOfBaseType = 32, - PropertyOfInstance = 33, - PropertyOfScript = 34, - ObjectTooBig = 35, - NodePathValidTypes = 36, - SaveFile = 37, - GlobalSaveFile = 38, - IntIsObjectid = 39, - IntIsPointer = 41, - ArrayType = 40, - LocaleId = 42, - LocalizableString = 43, - NodeType = 44, + ObjectId = 22, + TypeString = 23, + NodePathToEditedNode = 24, + MethodOfVariantType = 25, + MethodOfBaseType = 26, + MethodOfInstance = 27, + MethodOfScript = 28, + PropertyOfVariantType = 29, + PropertyOfBaseType = 30, + PropertyOfInstance = 31, + PropertyOfScript = 32, + ObjectTooBig = 33, + NodePathValidTypes = 34, + SaveFile = 35, + GlobalSaveFile = 36, + IntIsObjectid = 37, + IntIsPointer = 38, + ArrayType = 39, + LocaleId = 40, + LocalizableString = 41, + NodeType = 42, + HideQuaternionEdit = 43, + Password = 44, Max = 45 } @@ -128,12 +128,14 @@ namespace Godot.SourceGenerators DeferredSetResource = 33554432, EditorInstantiateObject = 67108864, EditorBasicSetting = 134217728, + ReadOnly = 268435456, Array = 536870912, Default = 6, DefaultIntl = 38, NoEditor = 2 } + [Flags] public enum MethodFlags { Normal = 1, diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotMemberData.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotMemberData.cs index db395e21cb..abd8079922 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotMemberData.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotMemberData.cs @@ -3,7 +3,7 @@ using Microsoft.CodeAnalysis; namespace Godot.SourceGenerators { - public struct GodotMethodData + public readonly struct GodotMethodData { public GodotMethodData(IMethodSymbol method, ImmutableArray<MarshalType> paramTypes, ImmutableArray<ITypeSymbol> paramTypeSymbols, MarshalType? retType, ITypeSymbol? retSymbol) @@ -22,7 +22,7 @@ namespace Godot.SourceGenerators public ITypeSymbol? RetSymbol { get; } } - public struct GodotSignalDelegateData + public readonly struct GodotSignalDelegateData { public GodotSignalDelegateData(string name, INamedTypeSymbol delegateSymbol, GodotMethodData invokeMethodData) { @@ -36,7 +36,7 @@ namespace Godot.SourceGenerators public GodotMethodData InvokeMethodData { get; } } - public struct GodotPropertyData + public readonly struct GodotPropertyData { public GodotPropertyData(IPropertySymbol propertySymbol, MarshalType type) { @@ -48,7 +48,7 @@ namespace Godot.SourceGenerators public MarshalType Type { get; } } - public struct GodotFieldData + public readonly struct GodotFieldData { public GodotFieldData(IFieldSymbol fieldSymbol, MarshalType type) { diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MarshalUtils.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MarshalUtils.cs index bd40675fd3..4fdd40f638 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MarshalUtils.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MarshalUtils.cs @@ -220,7 +220,7 @@ namespace Godot.SourceGenerators _ => null }; case "Collections" - when type.ContainingNamespace?.FullQualifiedName() == "Godot.Collections": + when type.ContainingNamespace?.FullQualifiedNameOmitGlobal() == "Godot.Collections": return type switch { { Name: "Dictionary" } => @@ -367,7 +367,7 @@ namespace Godot.SourceGenerators MarshalType.SignalInfo => source.Append(VariantUtils, ".ConvertToSignalInfo(", inputExpr, ")"), MarshalType.Enum => - source.Append("(", typeSymbol.FullQualifiedName(), + source.Append("(", typeSymbol.FullQualifiedNameIncludeGlobal(), ")", VariantUtils, ".ConvertToInt32(", inputExpr, ")"), MarshalType.ByteArray => source.Append(VariantUtils, ".ConvertAsPackedByteArrayToSystemArray(", inputExpr, ")"), @@ -389,7 +389,7 @@ namespace Godot.SourceGenerators source.Append(VariantUtils, ".ConvertAsPackedColorArrayToSystemArray(", inputExpr, ")"), MarshalType.GodotObjectOrDerivedArray => source.Append(VariantUtils, ".ConvertToSystemArrayOfGodotObject<", - ((IArrayTypeSymbol)typeSymbol).ElementType.FullQualifiedName(), ">(", inputExpr, ")"), + ((IArrayTypeSymbol)typeSymbol).ElementType.FullQualifiedNameIncludeGlobal(), ">(", inputExpr, ")"), MarshalType.SystemArrayOfStringName => source.Append(VariantUtils, ".ConvertToSystemArrayOfStringName(", inputExpr, ")"), MarshalType.SystemArrayOfNodePath => @@ -399,7 +399,7 @@ namespace Godot.SourceGenerators MarshalType.Variant => source.Append("global::Godot.Variant.CreateCopyingBorrowed(", inputExpr, ")"), MarshalType.GodotObjectOrDerived => - source.Append("(", typeSymbol.FullQualifiedName(), + source.Append("(", typeSymbol.FullQualifiedNameIncludeGlobal(), ")", VariantUtils, ".ConvertToGodotObject(", inputExpr, ")"), MarshalType.StringName => source.Append(VariantUtils, ".ConvertToStringNameObject(", inputExpr, ")"), @@ -413,11 +413,11 @@ namespace Godot.SourceGenerators source.Append(VariantUtils, ".ConvertToArrayObject(", inputExpr, ")"), MarshalType.GodotGenericDictionary => source.Append(VariantUtils, ".ConvertToDictionaryObject<", - ((INamedTypeSymbol)typeSymbol).TypeArguments[0].FullQualifiedName(), ", ", - ((INamedTypeSymbol)typeSymbol).TypeArguments[1].FullQualifiedName(), ">(", inputExpr, ")"), + ((INamedTypeSymbol)typeSymbol).TypeArguments[0].FullQualifiedNameIncludeGlobal(), ", ", + ((INamedTypeSymbol)typeSymbol).TypeArguments[1].FullQualifiedNameIncludeGlobal(), ">(", inputExpr, ")"), MarshalType.GodotGenericArray => source.Append(VariantUtils, ".ConvertToArrayObject<", - ((INamedTypeSymbol)typeSymbol).TypeArguments[0].FullQualifiedName(), ">(", inputExpr, ")"), + ((INamedTypeSymbol)typeSymbol).TypeArguments[0].FullQualifiedNameIncludeGlobal(), ">(", inputExpr, ")"), _ => throw new ArgumentOutOfRangeException(nameof(marshalType), marshalType, "Received unexpected marshal type") }; @@ -578,7 +578,7 @@ namespace Godot.SourceGenerators MarshalType.Callable => source.Append(inputExpr, ".AsCallable()"), MarshalType.SignalInfo => source.Append(inputExpr, ".AsSignalInfo()"), MarshalType.Enum => - source.Append("(", typeSymbol.FullQualifiedName(), ")", inputExpr, ".AsInt64()"), + source.Append("(", typeSymbol.FullQualifiedNameIncludeGlobal(), ")", inputExpr, ".AsInt64()"), MarshalType.ByteArray => source.Append(inputExpr, ".AsByteArray()"), MarshalType.Int32Array => source.Append(inputExpr, ".AsInt32Array()"), MarshalType.Int64Array => source.Append(inputExpr, ".AsInt64Array()"), @@ -589,23 +589,23 @@ namespace Godot.SourceGenerators MarshalType.Vector3Array => source.Append(inputExpr, ".AsVector3Array()"), MarshalType.ColorArray => source.Append(inputExpr, ".AsColorArray()"), MarshalType.GodotObjectOrDerivedArray => source.Append(inputExpr, ".AsGodotObjectArray<", - ((IArrayTypeSymbol)typeSymbol).ElementType.FullQualifiedName(), ">()"), + ((IArrayTypeSymbol)typeSymbol).ElementType.FullQualifiedNameIncludeGlobal(), ">()"), MarshalType.SystemArrayOfStringName => source.Append(inputExpr, ".AsSystemArrayOfStringName()"), MarshalType.SystemArrayOfNodePath => source.Append(inputExpr, ".AsSystemArrayOfNodePath()"), MarshalType.SystemArrayOfRID => source.Append(inputExpr, ".AsSystemArrayOfRID()"), MarshalType.Variant => source.Append(inputExpr), MarshalType.GodotObjectOrDerived => source.Append("(", - typeSymbol.FullQualifiedName(), ")", inputExpr, ".AsGodotObject()"), + typeSymbol.FullQualifiedNameIncludeGlobal(), ")", inputExpr, ".AsGodotObject()"), MarshalType.StringName => source.Append(inputExpr, ".AsStringName()"), MarshalType.NodePath => source.Append(inputExpr, ".AsNodePath()"), MarshalType.RID => source.Append(inputExpr, ".AsRID()"), MarshalType.GodotDictionary => source.Append(inputExpr, ".AsGodotDictionary()"), MarshalType.GodotArray => source.Append(inputExpr, ".AsGodotArray()"), MarshalType.GodotGenericDictionary => source.Append(inputExpr, ".AsGodotDictionary<", - ((INamedTypeSymbol)typeSymbol).TypeArguments[0].FullQualifiedName(), ", ", - ((INamedTypeSymbol)typeSymbol).TypeArguments[1].FullQualifiedName(), ">()"), + ((INamedTypeSymbol)typeSymbol).TypeArguments[0].FullQualifiedNameIncludeGlobal(), ", ", + ((INamedTypeSymbol)typeSymbol).TypeArguments[1].FullQualifiedNameIncludeGlobal(), ">()"), MarshalType.GodotGenericArray => source.Append(inputExpr, ".AsGodotArray<", - ((INamedTypeSymbol)typeSymbol).TypeArguments[0].FullQualifiedName(), ">()"), + ((INamedTypeSymbol)typeSymbol).TypeArguments[0].FullQualifiedNameIncludeGlobal(), ">()"), _ => throw new ArgumentOutOfRangeException(nameof(marshalType), marshalType, "Received unexpected marshal type") }; diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MethodInfo.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MethodInfo.cs index 81c6f2b7d5..bb9be862c4 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MethodInfo.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MethodInfo.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; namespace Godot.SourceGenerators { - internal struct MethodInfo + internal readonly struct MethodInfo { public MethodInfo(string name, PropertyInfo returnVal, MethodFlags flags, List<PropertyInfo>? arguments, diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/PropertyInfo.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/PropertyInfo.cs index b345f5f84d..2b89633ef6 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/PropertyInfo.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/PropertyInfo.cs @@ -1,6 +1,6 @@ namespace Godot.SourceGenerators { - internal struct PropertyInfo + internal readonly struct PropertyInfo { public PropertyInfo(VariantType type, string name, PropertyHint hint, string? hintString, PropertyUsageFlags usage, bool exported) diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptMethodsGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptMethodsGenerator.cs index d5d80df643..2f51018293 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptMethodsGenerator.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptMethodsGenerator.cs @@ -80,13 +80,13 @@ namespace Godot.SourceGenerators { INamespaceSymbol namespaceSymbol = symbol.ContainingNamespace; string classNs = namespaceSymbol != null && !namespaceSymbol.IsGlobalNamespace ? - namespaceSymbol.FullQualifiedName() : + namespaceSymbol.FullQualifiedNameOmitGlobal() : string.Empty; bool hasNamespace = classNs.Length != 0; bool isInnerClass = symbol.ContainingType != null; - string uniqueHint = symbol.FullQualifiedName().SanitizeQualifiedNameForUniqueHint() + string uniqueHint = symbol.FullQualifiedNameOmitGlobal().SanitizeQualifiedNameForUniqueHint() + "_ScriptMethods.generated"; var source = new StringBuilder(); @@ -135,7 +135,7 @@ namespace Godot.SourceGenerators source.Append("#pragma warning disable CS0109 // Disable warning about redundant 'new' keyword\n"); - source.Append($" public new class MethodName : {symbol.BaseType.FullQualifiedName()}.MethodName {{\n"); + source.Append($" public new class MethodName : {symbol.BaseType.FullQualifiedNameIncludeGlobal()}.MethodName {{\n"); // Generate cached StringNames for methods and properties, for fast lookup @@ -146,7 +146,7 @@ namespace Godot.SourceGenerators foreach (string methodName in distinctMethodNames) { - source.Append(" public new static readonly StringName "); + source.Append(" public new static readonly global::Godot.StringName "); source.Append(methodName); source.Append(" = \""); source.Append(methodName); @@ -159,7 +159,7 @@ namespace Godot.SourceGenerators if (godotClassMethods.Length > 0) { - const string listType = "System.Collections.Generic.List<global::Godot.Bridge.MethodInfo>"; + const string listType = "global::System.Collections.Generic.List<global::Godot.Bridge.MethodInfo>"; source.Append(" internal new static ") .Append(listType) @@ -248,7 +248,7 @@ namespace Godot.SourceGenerators AppendPropertyInfo(source, methodInfo.ReturnVal); - source.Append(", flags: (Godot.MethodFlags)") + source.Append(", flags: (global::Godot.MethodFlags)") .Append((int)methodInfo.Flags) .Append(", arguments: "); @@ -276,15 +276,15 @@ namespace Godot.SourceGenerators private static void AppendPropertyInfo(StringBuilder source, PropertyInfo propertyInfo) { - source.Append("new(type: (Godot.Variant.Type)") + source.Append("new(type: (global::Godot.Variant.Type)") .Append((int)propertyInfo.Type) .Append(", name: \"") .Append(propertyInfo.Name) - .Append("\", hint: (Godot.PropertyHint)") + .Append("\", hint: (global::Godot.PropertyHint)") .Append((int)propertyInfo.Hint) .Append(", hintString: \"") .Append(propertyInfo.HintString) - .Append("\", usage: (Godot.PropertyUsageFlags)") + .Append("\", usage: (global::Godot.PropertyUsageFlags)") .Append((int)propertyInfo.Usage) .Append(", exported: ") .Append(propertyInfo.Exported ? "true" : "false") diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPathAttributeGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPathAttributeGenerator.cs index ccfb405d26..fb32f6192f 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPathAttributeGenerator.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPathAttributeGenerator.cs @@ -92,11 +92,11 @@ namespace Godot.SourceGenerators INamespaceSymbol namespaceSymbol = symbol.ContainingNamespace; string classNs = namespaceSymbol != null && !namespaceSymbol.IsGlobalNamespace ? - namespaceSymbol.FullQualifiedName() : + namespaceSymbol.FullQualifiedNameOmitGlobal() : string.Empty; bool hasNamespace = classNs.Length != 0; - string uniqueHint = symbol.FullQualifiedName().SanitizeQualifiedNameForUniqueHint() + string uniqueHint = symbol.FullQualifiedNameOmitGlobal().SanitizeQualifiedNameForUniqueHint() + "_ScriptPath.generated"; var source = new StringBuilder(); diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs index 1198c633d9..252f162b0c 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs @@ -66,13 +66,13 @@ namespace Godot.SourceGenerators { INamespaceSymbol namespaceSymbol = symbol.ContainingNamespace; string classNs = namespaceSymbol != null && !namespaceSymbol.IsGlobalNamespace ? - namespaceSymbol.FullQualifiedName() : + namespaceSymbol.FullQualifiedNameOmitGlobal() : string.Empty; bool hasNamespace = classNs.Length != 0; bool isInnerClass = symbol.ContainingType != null; - string uniqueHint = symbol.FullQualifiedName().SanitizeQualifiedNameForUniqueHint() + string uniqueHint = symbol.FullQualifiedNameOmitGlobal().SanitizeQualifiedNameForUniqueHint() + "_ScriptProperties.generated"; var source = new StringBuilder(); @@ -124,14 +124,14 @@ namespace Godot.SourceGenerators source.Append("#pragma warning disable CS0109 // Disable warning about redundant 'new' keyword\n"); - source.Append($" public new class PropertyName : {symbol.BaseType.FullQualifiedName()}.PropertyName {{\n"); + source.Append($" public new class PropertyName : {symbol.BaseType.FullQualifiedNameIncludeGlobal()}.PropertyName {{\n"); // Generate cached StringNames for methods and properties, for fast lookup foreach (var property in godotClassProperties) { string propertyName = property.PropertySymbol.Name; - source.Append(" public new static readonly StringName "); + source.Append(" public new static readonly global::Godot.StringName "); source.Append(propertyName); source.Append(" = \""); source.Append(propertyName); @@ -141,7 +141,7 @@ namespace Godot.SourceGenerators foreach (var field in godotClassFields) { string fieldName = field.FieldSymbol.Name; - source.Append(" public new static readonly StringName "); + source.Append(" public new static readonly global::Godot.StringName "); source.Append(fieldName); source.Append(" = \""); source.Append(fieldName); @@ -216,7 +216,7 @@ namespace Godot.SourceGenerators // Generate GetGodotPropertyList - string dictionaryType = "System.Collections.Generic.List<global::Godot.Bridge.PropertyInfo>"; + string dictionaryType = "global::System.Collections.Generic.List<global::Godot.Bridge.PropertyInfo>"; source.Append(" internal new static ") .Append(dictionaryType) @@ -292,7 +292,7 @@ namespace Godot.SourceGenerators source.Append("if (name == PropertyName.") .Append(propertyMemberName) .Append(") {\n") - .Append(" ") + .Append(" this.") .Append(propertyMemberName) .Append(" = ") .AppendNativeVariantToManagedExpr("value", propertyTypeSymbol, propertyMarshalType) @@ -317,7 +317,7 @@ namespace Godot.SourceGenerators .Append(propertyMemberName) .Append(") {\n") .Append(" value = ") - .AppendManagedToNativeVariantExpr(propertyMemberName, propertyMarshalType) + .AppendManagedToNativeVariantExpr("this." + propertyMemberName, propertyMarshalType) .Append(";\n") .Append(" return true;\n") .Append(" }\n"); @@ -340,15 +340,15 @@ namespace Godot.SourceGenerators private static void AppendPropertyInfo(StringBuilder source, PropertyInfo propertyInfo) { - source.Append(" properties.Add(new(type: (Godot.Variant.Type)") + source.Append(" properties.Add(new(type: (global::Godot.Variant.Type)") .Append((int)propertyInfo.Type) .Append(", name: PropertyName.") .Append(propertyInfo.Name) - .Append(", hint: (Godot.PropertyHint)") + .Append(", hint: (global::Godot.PropertyHint)") .Append((int)propertyInfo.Hint) .Append(", hintString: \"") .Append(propertyInfo.HintString) - .Append("\", usage: (Godot.PropertyUsageFlags)") + .Append("\", usage: (global::Godot.PropertyUsageFlags)") .Append((int)propertyInfo.Usage) .Append(", exported: ") .Append(propertyInfo.Exported ? "true" : "false") diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertyDefValGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertyDefValGenerator.cs index 98b9745c16..63339b3487 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertyDefValGenerator.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertyDefValGenerator.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; @@ -66,21 +67,17 @@ namespace Godot.SourceGenerators { INamespaceSymbol namespaceSymbol = symbol.ContainingNamespace; string classNs = namespaceSymbol != null && !namespaceSymbol.IsGlobalNamespace ? - namespaceSymbol.FullQualifiedName() : + namespaceSymbol.FullQualifiedNameOmitGlobal() : string.Empty; bool hasNamespace = classNs.Length != 0; bool isInnerClass = symbol.ContainingType != null; - string uniqueHint = symbol.FullQualifiedName().SanitizeQualifiedNameForUniqueHint() + string uniqueHint = symbol.FullQualifiedNameOmitGlobal().SanitizeQualifiedNameForUniqueHint() + "_ScriptPropertyDefVal.generated"; var source = new StringBuilder(); - source.Append("using Godot;\n"); - source.Append("using Godot.NativeInterop;\n"); - source.Append("\n"); - if (hasNamespace) { source.Append("namespace "); @@ -163,14 +160,69 @@ namespace Godot.SourceGenerators continue; } - // TODO: Detect default value from simple property getters (currently we only detect from initializers) - - EqualsValueClauseSyntax? initializer = property.DeclaringSyntaxReferences - .Select(r => r.GetSyntax() as PropertyDeclarationSyntax) - .Select(s => s?.Initializer ?? null) - .FirstOrDefault(); + var propertyDeclarationSyntax = property.DeclaringSyntaxReferences + .Select(r => r.GetSyntax() as PropertyDeclarationSyntax).FirstOrDefault(); - string? value = initializer?.Value.ToString(); + // Fully qualify the value to avoid issues with namespaces. + string? value = null; + if (propertyDeclarationSyntax != null) + { + if (propertyDeclarationSyntax.Initializer != null) + { + var sm = context.Compilation.GetSemanticModel(propertyDeclarationSyntax.Initializer.SyntaxTree); + value = propertyDeclarationSyntax.Initializer.Value.FullQualifiedSyntax(sm); + } + else + { + var propertyGet = propertyDeclarationSyntax.AccessorList?.Accessors.Where(a => a.Keyword.IsKind(SyntaxKind.GetKeyword)).FirstOrDefault(); + if (propertyGet != null) + { + if (propertyGet.ExpressionBody != null) + { + if (propertyGet.ExpressionBody.Expression is IdentifierNameSyntax identifierNameSyntax) + { + var sm = context.Compilation.GetSemanticModel(identifierNameSyntax.SyntaxTree); + var fieldSymbol = sm.GetSymbolInfo(identifierNameSyntax).Symbol as IFieldSymbol; + EqualsValueClauseSyntax? initializer = fieldSymbol?.DeclaringSyntaxReferences + .Select(r => r.GetSyntax()) + .OfType<VariableDeclaratorSyntax>() + .Select(s => s.Initializer) + .FirstOrDefault(i => i != null); + + if (initializer != null) + { + sm = context.Compilation.GetSemanticModel(initializer.SyntaxTree); + value = initializer.Value.FullQualifiedSyntax(sm); + } + } + } + else + { + var returns = propertyGet.DescendantNodes().OfType<ReturnStatementSyntax>(); + if (returns.Count() == 1) + {// Generate only single return + var returnStatementSyntax = returns.Single(); + if (returnStatementSyntax.Expression is IdentifierNameSyntax identifierNameSyntax) + { + var sm = context.Compilation.GetSemanticModel(identifierNameSyntax.SyntaxTree); + var fieldSymbol = sm.GetSymbolInfo(identifierNameSyntax).Symbol as IFieldSymbol; + EqualsValueClauseSyntax? initializer = fieldSymbol?.DeclaringSyntaxReferences + .Select(r => r.GetSyntax()) + .OfType<VariableDeclaratorSyntax>() + .Select(s => s.Initializer) + .FirstOrDefault(i => i != null); + + if (initializer != null) + { + sm = context.Compilation.GetSemanticModel(initializer.SyntaxTree); + value = initializer.Value.FullQualifiedSyntax(sm); + } + } + } + } + } + } + } exportedMembers.Add(new ExportedPropertyMetadata( property.Name, marshalType.Value, propertyType, value)); @@ -207,7 +259,13 @@ namespace Godot.SourceGenerators .Select(s => s.Initializer) .FirstOrDefault(i => i != null); - string? value = initializer?.Value.ToString(); + // This needs to be fully qualified to avoid issues with namespaces. + string? value = null; + if (initializer != null) + { + var sm = context.Compilation.GetSemanticModel(initializer.SyntaxTree); + value = initializer.Value.FullQualifiedSyntax(sm); + } exportedMembers.Add(new ExportedPropertyMetadata( field.Name, marshalType.Value, fieldType, value)); @@ -219,7 +277,7 @@ namespace Godot.SourceGenerators { source.Append("#pragma warning disable CS0109 // Disable warning about redundant 'new' keyword\n"); - string dictionaryType = "System.Collections.Generic.Dictionary<StringName, object>"; + string dictionaryType = "System.Collections.Generic.Dictionary<Godot.StringName, object>"; source.Append("#if TOOLS\n"); source.Append(" internal new static "); @@ -237,7 +295,7 @@ namespace Godot.SourceGenerators string defaultValueLocalName = string.Concat("__", exportedMember.Name, "_default_value"); source.Append(" "); - source.Append(exportedMember.TypeSymbol.FullQualifiedName()); + source.Append(exportedMember.TypeSymbol.FullQualifiedNameIncludeGlobal()); source.Append(" "); source.Append(defaultValueLocalName); source.Append(" = "); diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSerializationGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSerializationGenerator.cs index 11e0a6fa21..ed877cbd17 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSerializationGenerator.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSerializationGenerator.cs @@ -66,13 +66,13 @@ namespace Godot.SourceGenerators { INamespaceSymbol namespaceSymbol = symbol.ContainingNamespace; string classNs = namespaceSymbol != null && !namespaceSymbol.IsGlobalNamespace ? - namespaceSymbol.FullQualifiedName() : + namespaceSymbol.FullQualifiedNameOmitGlobal() : string.Empty; bool hasNamespace = classNs.Length != 0; bool isInnerClass = symbol.ContainingType != null; - string uniqueHint = symbol.FullQualifiedName().SanitizeQualifiedNameForUniqueHint() + string uniqueHint = symbol.FullQualifiedNameOmitGlobal().SanitizeQualifiedNameForUniqueHint() + "_ScriptSerialization.generated"; var source = new StringBuilder(); @@ -241,7 +241,7 @@ namespace Godot.SourceGenerators foreach (var signalDelegate in godotSignalDelegates) { string signalName = signalDelegate.Name; - string signalDelegateQualifiedName = signalDelegate.DelegateSymbol.FullQualifiedName(); + string signalDelegateQualifiedName = signalDelegate.DelegateSymbol.FullQualifiedNameIncludeGlobal(); source.Append(" if (info.TryGetSignalEventDelegate<") .Append(signalDelegateQualifiedName) diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSignalsGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSignalsGenerator.cs index 50196b84f0..119cc9d4f0 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSignalsGenerator.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSignalsGenerator.cs @@ -75,13 +75,13 @@ namespace Godot.SourceGenerators { INamespaceSymbol namespaceSymbol = symbol.ContainingNamespace; string classNs = namespaceSymbol != null && !namespaceSymbol.IsGlobalNamespace ? - namespaceSymbol.FullQualifiedName() : + namespaceSymbol.FullQualifiedNameOmitGlobal() : string.Empty; bool hasNamespace = classNs.Length != 0; bool isInnerClass = symbol.ContainingType != null; - string uniqueHint = symbol.FullQualifiedName().SanitizeQualifiedNameForUniqueHint() + string uniqueHint = symbol.FullQualifiedNameOmitGlobal().SanitizeQualifiedNameForUniqueHint() + "_ScriptSignals.generated"; var source = new StringBuilder(); @@ -176,14 +176,14 @@ namespace Godot.SourceGenerators source.Append("#pragma warning disable CS0109 // Disable warning about redundant 'new' keyword\n"); - source.Append($" public new class SignalName : {symbol.BaseType.FullQualifiedName()}.SignalName {{\n"); + source.Append($" public new class SignalName : {symbol.BaseType.FullQualifiedNameIncludeGlobal()}.SignalName {{\n"); // Generate cached StringNames for methods and properties, for fast lookup foreach (var signalDelegate in godotSignalDelegates) { string signalName = signalDelegate.Name; - source.Append(" public new static readonly StringName "); + source.Append(" public new static readonly global::Godot.StringName "); source.Append(signalName); source.Append(" = \""); source.Append(signalName); @@ -196,7 +196,7 @@ namespace Godot.SourceGenerators if (godotSignalDelegates.Count > 0) { - const string listType = "System.Collections.Generic.List<global::Godot.Bridge.MethodInfo>"; + const string listType = "global::System.Collections.Generic.List<global::Godot.Bridge.MethodInfo>"; source.Append(" internal new static ") .Append(listType) @@ -231,15 +231,15 @@ namespace Godot.SourceGenerators // as it doesn't emit the signal, only the event delegates. This can confuse users. // Maybe we should directly connect the delegates, as we do with native signals? source.Append(" private ") - .Append(signalDelegate.DelegateSymbol.FullQualifiedName()) + .Append(signalDelegate.DelegateSymbol.FullQualifiedNameIncludeGlobal()) .Append(" backing_") .Append(signalName) .Append(";\n"); - source.Append($" /// <inheritdoc cref=\"{signalDelegate.DelegateSymbol.FullQualifiedName()}\"/>\n"); + source.Append($" /// <inheritdoc cref=\"{signalDelegate.DelegateSymbol.FullQualifiedNameIncludeGlobal()}\"/>\n"); source.Append(" public event ") - .Append(signalDelegate.DelegateSymbol.FullQualifiedName()) + .Append(signalDelegate.DelegateSymbol.FullQualifiedNameIncludeGlobal()) .Append(" ") .Append(signalName) .Append(" {\n") @@ -300,7 +300,7 @@ namespace Godot.SourceGenerators AppendPropertyInfo(source, methodInfo.ReturnVal); - source.Append(", flags: (Godot.MethodFlags)") + source.Append(", flags: (global::Godot.MethodFlags)") .Append((int)methodInfo.Flags) .Append(", arguments: "); @@ -328,15 +328,15 @@ namespace Godot.SourceGenerators private static void AppendPropertyInfo(StringBuilder source, PropertyInfo propertyInfo) { - source.Append("new(type: (Godot.Variant.Type)") + source.Append("new(type: (global::Godot.Variant.Type)") .Append((int)propertyInfo.Type) .Append(", name: \"") .Append(propertyInfo.Name) - .Append("\", hint: (Godot.PropertyHint)") + .Append("\", hint: (global::Godot.PropertyHint)") .Append((int)propertyInfo.Hint) .Append(", hintString: \"") .Append(propertyInfo.HintString) - .Append("\", usage: (Godot.PropertyUsageFlags)") + .Append("\", usage: (global::Godot.PropertyUsageFlags)") .Append((int)propertyInfo.Usage) .Append(", exported: ") .Append(propertyInfo.Exported ? "true" : "false") diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Utils/SemaphoreExtensions.cs b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Utils/SemaphoreExtensions.cs index 9d593fbf8a..ab21527344 100644 --- a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Utils/SemaphoreExtensions.cs +++ b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Utils/SemaphoreExtensions.cs @@ -13,7 +13,7 @@ namespace GodotTools.IdeMessaging.Utils return waitAsyncTask.ContinueWith<IDisposable>(t => wrapper, cancellationToken).ConfigureAwait(false); } - private struct SemaphoreSlimWaitReleaseWrapper : IDisposable + private readonly struct SemaphoreSlimWaitReleaseWrapper : IDisposable { private readonly SemaphoreSlim semaphoreSlim; diff --git a/modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs b/modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs index 2184cae6d6..94efcba3f1 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs @@ -22,7 +22,7 @@ namespace GodotTools.Export public bool FullAot; private bool _useInterpreter; - public bool UseInterpreter { get => _useInterpreter && !LLVMOnly; set => _useInterpreter = value; } + public bool UseInterpreter { readonly get => _useInterpreter && !LLVMOnly; set => _useInterpreter = value; } public string[] ExtraAotOptions; public string[] ExtraOptimizerOptions; diff --git a/modules/mono/editor/GodotTools/GodotTools/PlaySettings.cs b/modules/mono/editor/GodotTools/GodotTools/PlaySettings.cs index 820d0c0b83..9a8fdcc7c5 100644 --- a/modules/mono/editor/GodotTools/GodotTools/PlaySettings.cs +++ b/modules/mono/editor/GodotTools/GodotTools/PlaySettings.cs @@ -1,6 +1,6 @@ namespace GodotTools { - public struct PlaySettings + public readonly struct PlaySettings { public bool HasDebugger { get; } public string DebuggerHost { get; } diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp index b90321b586..9185506776 100644 --- a/modules/mono/editor/bindings_generator.cpp +++ b/modules/mono/editor/bindings_generator.cpp @@ -2274,7 +2274,7 @@ Error BindingsGenerator::_generate_cs_signal(const BindingsGenerator::TypeInterf p_output.append(");\n"); // Generate Callable trampoline for the delegate - p_output << MEMBER_BEGIN "private static unsafe void " << p_isignal.proxy_name << "Trampoline" + p_output << MEMBER_BEGIN "private static void " << p_isignal.proxy_name << "Trampoline" << "(object delegateObj, NativeVariantPtrArgs args, out godot_variant ret)\n" << INDENT1 "{\n" << INDENT2 "Callable.ThrowIfArgCountMismatch(args, " << itos(p_isignal.arguments.size()) << ");\n" @@ -2289,9 +2289,8 @@ Error BindingsGenerator::_generate_cs_signal(const BindingsGenerator::TypeInterf p_output << ","; } - // TODO: We don't need to use VariantConversionCallbacks. We have the type information so we can use [cs_variant_to_managed] and [cs_managed_to_variant]. - p_output << "\n" INDENT3 "VariantConversionCallbacks.GetToManagedCallback<" - << arg_type->cs_type << ">()(args[" << itos(idx) << "])"; + p_output << sformat(arg_type->cs_variant_to_managed, + "args[" + itos(idx) + "]", arg_type->cs_type, arg_type->name); idx++; } @@ -2543,15 +2542,13 @@ Error BindingsGenerator::_generate_cs_native_calls(const InternalCall &p_icall, << INDENT2 "int total_length = " << real_argc_str << " + vararg_length;\n"; r_output << INDENT2 "Span<godot_variant.movable> varargs_span = vararg_length <= VarArgsSpanThreshold ?\n" - << INDENT3 "stackalloc godot_variant.movable[VarArgsSpanThreshold].Cleared() :\n" + << INDENT3 "stackalloc godot_variant.movable[VarArgsSpanThreshold] :\n" << INDENT3 "new godot_variant.movable[vararg_length];\n"; r_output << INDENT2 "Span<IntPtr> " C_LOCAL_PTRCALL_ARGS "_span = total_length <= VarArgsSpanThreshold ?\n" << INDENT3 "stackalloc IntPtr[VarArgsSpanThreshold] :\n" << INDENT3 "new IntPtr[total_length];\n"; - r_output << INDENT2 "using var variantSpanDisposer = new VariantSpanDisposer(varargs_span);\n"; - r_output << INDENT2 "fixed (godot_variant.movable* varargs = &MemoryMarshal.GetReference(varargs_span))\n" << INDENT2 "fixed (IntPtr* " C_LOCAL_PTRCALL_ARGS " = " "&MemoryMarshal.GetReference(" C_LOCAL_PTRCALL_ARGS "_span))\n" |