浏览代码

C#: Fix generator crash w/ generic arrays

Paul Joannon 1 年之前
父节点
当前提交
aba787393f

+ 9 - 0
modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/ScriptPropertiesGeneratorTests.cs

@@ -57,4 +57,13 @@ public class ScriptPropertiesGeneratorTests
             "ScriptBoilerplate_ScriptProperties.generated.cs", "OuterClass.NestedClass_ScriptProperties.generated.cs"
         );
     }
+
+    [Fact]
+    public async void AbstractGenericNode()
+    {
+        await CSharpSourceGeneratorVerifier<ScriptPropertiesGenerator>.Verify(
+            "AbstractGenericNode.cs",
+            "AbstractGenericNode(Of T)_ScriptProperties.generated.cs"
+        );
+    }
 }

+ 49 - 0
modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/AbstractGenericNode(Of T)_ScriptProperties.generated.cs

@@ -0,0 +1,49 @@
+using Godot;
+using Godot.NativeInterop;
+
+partial class AbstractGenericNode<T>
+{
+#pragma warning disable CS0109 // Disable warning about redundant 'new' keyword
+    /// <summary>
+    /// Cached StringNames for the properties and fields contained in this class, for fast lookup.
+    /// </summary>
+    public new class PropertyName : global::Godot.Node.PropertyName {
+        /// <summary>
+        /// Cached name for the 'MyArray' property.
+        /// </summary>
+        public new static readonly global::Godot.StringName MyArray = "MyArray";
+    }
+    /// <inheritdoc/>
+    [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
+    protected override bool SetGodotClassPropertyValue(in godot_string_name name, in godot_variant value)
+    {
+        if (name == PropertyName.MyArray) {
+            this.MyArray = global::Godot.NativeInterop.VariantUtils.ConvertToArray<T>(value);
+            return true;
+        }
+        return base.SetGodotClassPropertyValue(name, value);
+    }
+    /// <inheritdoc/>
+    [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
+    protected override bool GetGodotClassPropertyValue(in godot_string_name name, out godot_variant value)
+    {
+        if (name == PropertyName.MyArray) {
+            value = global::Godot.NativeInterop.VariantUtils.CreateFromArray(this.MyArray);
+            return true;
+        }
+        return base.GetGodotClassPropertyValue(name, out value);
+    }
+    /// <summary>
+    /// Get the property information for all the properties declared in this class.
+    /// This method is used by Godot to register the available properties in the editor.
+    /// Do not call this method.
+    /// </summary>
+    [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
+    internal new static global::System.Collections.Generic.List<global::Godot.Bridge.PropertyInfo> GetGodotPropertyList()
+    {
+        var properties = new global::System.Collections.Generic.List<global::Godot.Bridge.PropertyInfo>();
+        properties.Add(new(type: (global::Godot.Variant.Type)28, name: PropertyName.MyArray, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+        return properties;
+    }
+#pragma warning restore CS0109
+}

+ 7 - 0
modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/AbstractGenericNode.cs

@@ -0,0 +1,7 @@
+using Godot;
+
+public abstract partial class AbstractGenericNode<[MustBeVariant] T> : Node
+{
+    [Export] // This should be included, but without type hints.
+    public Godot.Collections.Array<T> MyArray { get; set; } = new();
+}

+ 4 - 1
modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs

@@ -658,7 +658,10 @@ namespace Godot.SourceGenerators
                 var elementType = MarshalUtils.GetArrayElementType(type);
 
                 if (elementType == null)
-                    return false; // Non-generic Array, so there's no hint to add
+                    return false; // Non-generic Array, so there's no hint to add.
+
+                if (elementType.TypeKind == TypeKind.TypeParameter)
+                    return false; // The generic is not constructed, we can't really hint anything.
 
                 var elementMarshalType = MarshalUtils.ConvertManagedTypeToMarshalType(elementType, typeCache)!.Value;
                 var elementVariantType = MarshalUtils.ConvertMarshalTypeToVariantType(elementMarshalType)!.Value;