summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWilliam Scalf <wscalf@gmail.com>2023-08-13 18:35:10 -0400
committerWilliam Scalf <wscalf@gmail.com>2023-08-13 18:35:10 -0400
commit41cf94e8b61ee81fc0e682f2ee4ea2c6df893d37 (patch)
treedf51a5d8f0f871b6d765c29f439cbde572ac2d9b
parent7ba79d68bd0f97797d7cb37452da6a036ba7c7c9 (diff)
downloadredot-engine-41cf94e8b61ee81fc0e682f2ee4ea2c6df893d37.tar.gz
Allow readonly and writeonly C# properties to be accessed from GDScript
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/OneWayProperties/AllReadOnly.cs10
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/OneWayProperties/AllWriteOnly.cs10
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/OneWayProperties/MixedReadOnlyWriteOnly.cs13
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ExtensionMethods.cs9
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs44
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSerializationGenerator.cs10
6 files changed, 66 insertions, 30 deletions
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/OneWayProperties/AllReadOnly.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/OneWayProperties/AllReadOnly.cs
new file mode 100644
index 0000000000..0c374169b9
--- /dev/null
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/OneWayProperties/AllReadOnly.cs
@@ -0,0 +1,10 @@
+namespace Godot.SourceGenerators.Sample
+{
+ public partial class AllReadOnly : GodotObject
+ {
+ public readonly string readonly_field = "foo";
+ public string readonly_auto_property { get; } = "foo";
+ public string readonly_property { get => "foo"; }
+ public string initonly_auto_property { get; init; }
+ }
+}
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/OneWayProperties/AllWriteOnly.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/OneWayProperties/AllWriteOnly.cs
new file mode 100644
index 0000000000..14a1802330
--- /dev/null
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/OneWayProperties/AllWriteOnly.cs
@@ -0,0 +1,10 @@
+using System;
+
+namespace Godot.SourceGenerators.Sample
+{
+ public partial class AllWriteOnly : GodotObject
+ {
+ bool writeonly_backing_field = false;
+ public bool writeonly_property { set => writeonly_backing_field = value; }
+ }
+}
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/OneWayProperties/MixedReadOnlyWriteOnly.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/OneWayProperties/MixedReadOnlyWriteOnly.cs
new file mode 100644
index 0000000000..f556bdc7e4
--- /dev/null
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/OneWayProperties/MixedReadOnlyWriteOnly.cs
@@ -0,0 +1,13 @@
+namespace Godot.SourceGenerators.Sample
+{
+ public partial class MixedReadonlyWriteOnly : GodotObject
+ {
+ public readonly string readonly_field = "foo";
+ public string readonly_auto_property { get; } = "foo";
+ public string readonly_property { get => "foo"; }
+ public string initonly_auto_property { get; init; }
+
+ bool writeonly_backing_field = false;
+ public bool writeonly_property { set => writeonly_backing_field = value; }
+ }
+}
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 b6ea4b8e88..5866db5144 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ExtensionMethods.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ExtensionMethods.cs
@@ -303,11 +303,6 @@ namespace Godot.SourceGenerators
{
foreach (var property in properties)
{
- // TODO: We should still restore read-only properties after reloading assembly. Two possible ways: reflection or turn RestoreGodotObjectData into a constructor overload.
- // Ignore properties without a getter, without a setter or with an init-only setter. Godot properties must be both readable and writable.
- if (property.IsWriteOnly || property.IsReadOnly || property.SetMethod!.IsInitOnly)
- continue;
-
var marshalType = MarshalUtils.ConvertManagedTypeToMarshalType(property.Type, typeCache);
if (marshalType == null)
@@ -325,10 +320,6 @@ namespace Godot.SourceGenerators
foreach (var field in fields)
{
// TODO: We should still restore read-only fields after reloading assembly. Two possible ways: reflection or turn RestoreGodotObjectData into a constructor overload.
- // Ignore properties without a getter or without a setter. Godot properties must be both readable and writable.
- if (field.IsReadOnly)
- continue;
-
var marshalType = MarshalUtils.ConvertManagedTypeToMarshalType(field.Type, typeCache);
if (marshalType == null)
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 94d8696717..219ab7aa44 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs
@@ -212,31 +212,37 @@ namespace Godot.SourceGenerators
}
// Generate GetGodotClassPropertyValue
+ bool allPropertiesAreWriteOnly = godotClassFields.Length == 0 && godotClassProperties.All(pi => pi.PropertySymbol.IsWriteOnly);
- source.Append(" /// <inheritdoc/>\n");
- source.Append(" [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]\n");
- source.Append(" protected override bool GetGodotClassPropertyValue(in godot_string_name name, ");
- source.Append("out godot_variant value)\n {\n");
-
- isFirstEntry = true;
- foreach (var property in godotClassProperties)
+ if (!allPropertiesAreWriteOnly)
{
- GeneratePropertyGetter(property.PropertySymbol.Name,
- property.PropertySymbol.Type, property.Type, source, isFirstEntry);
- isFirstEntry = false;
- }
+ source.Append(" /// <inheritdoc/>\n");
+ source.Append(" [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]\n");
+ source.Append(" protected override bool GetGodotClassPropertyValue(in godot_string_name name, ");
+ source.Append("out godot_variant value)\n {\n");
- foreach (var field in godotClassFields)
- {
- GeneratePropertyGetter(field.FieldSymbol.Name,
- field.FieldSymbol.Type, field.Type, source, isFirstEntry);
- isFirstEntry = false;
- }
+ isFirstEntry = true;
+ foreach (var property in godotClassProperties)
+ {
+ if (property.PropertySymbol.IsWriteOnly)
+ continue;
- source.Append(" return base.GetGodotClassPropertyValue(name, out value);\n");
+ GeneratePropertyGetter(property.PropertySymbol.Name,
+ property.PropertySymbol.Type, property.Type, source, isFirstEntry);
+ isFirstEntry = false;
+ }
- source.Append(" }\n");
+ foreach (var field in godotClassFields)
+ {
+ GeneratePropertyGetter(field.FieldSymbol.Name,
+ field.FieldSymbol.Type, field.Type, source, isFirstEntry);
+ isFirstEntry = false;
+ }
+
+ source.Append(" return base.GetGodotClassPropertyValue(name, out value);\n");
+ source.Append(" }\n");
+ }
// Generate GetGodotPropertyList
const string dictionaryType = "global::System.Collections.Generic.List<global::Godot.Bridge.PropertyInfo>";
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 231a7be021..9de99414b6 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSerializationGenerator.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSerializationGenerator.cs
@@ -119,8 +119,14 @@ namespace Godot.SourceGenerators
.Where(s => !s.IsStatic && s.Kind == SymbolKind.Field && !s.IsImplicitlyDeclared)
.Cast<IFieldSymbol>();
- var godotClassProperties = propertySymbols.WhereIsGodotCompatibleType(typeCache).ToArray();
- var godotClassFields = fieldSymbols.WhereIsGodotCompatibleType(typeCache).ToArray();
+ // TODO: We should still restore read-only properties after reloading assembly. Two possible ways: reflection or turn RestoreGodotObjectData into a constructor overload.
+ // Ignore properties without a getter, without a setter or with an init-only setter. Godot properties must be both readable and writable.
+ var godotClassProperties = propertySymbols.Where(property => !(property.IsReadOnly || property.IsWriteOnly || property.SetMethod!.IsInitOnly))
+ .WhereIsGodotCompatibleType(typeCache)
+ .ToArray();
+ var godotClassFields = fieldSymbols.Where(property => !property.IsReadOnly)
+ .WhereIsGodotCompatibleType(typeCache)
+ .ToArray();
var signalDelegateSymbols = members
.Where(s => s.Kind == SymbolKind.NamedType)