Allow readonly and writeonly C# properties to be accessed from GDScript
This commit is contained in:
parent
7ba79d68bd
commit
41cf94e8b6
@ -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; }
|
||||||
|
}
|
||||||
|
}
|
@ -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; }
|
||||||
|
}
|
||||||
|
}
|
@ -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; }
|
||||||
|
}
|
||||||
|
}
|
@ -303,11 +303,6 @@ namespace Godot.SourceGenerators
|
|||||||
{
|
{
|
||||||
foreach (var property in properties)
|
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);
|
var marshalType = MarshalUtils.ConvertManagedTypeToMarshalType(property.Type, typeCache);
|
||||||
|
|
||||||
if (marshalType == null)
|
if (marshalType == null)
|
||||||
@ -325,10 +320,6 @@ namespace Godot.SourceGenerators
|
|||||||
foreach (var field in fields)
|
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.
|
// 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);
|
var marshalType = MarshalUtils.ConvertManagedTypeToMarshalType(field.Type, typeCache);
|
||||||
|
|
||||||
if (marshalType == null)
|
if (marshalType == null)
|
||||||
|
@ -212,31 +212,37 @@ namespace Godot.SourceGenerators
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Generate GetGodotClassPropertyValue
|
// Generate GetGodotClassPropertyValue
|
||||||
|
bool allPropertiesAreWriteOnly = godotClassFields.Length == 0 && godotClassProperties.All(pi => pi.PropertySymbol.IsWriteOnly);
|
||||||
|
|
||||||
source.Append(" /// <inheritdoc/>\n");
|
if (!allPropertiesAreWriteOnly)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
GeneratePropertyGetter(property.PropertySymbol.Name,
|
source.Append(" /// <inheritdoc/>\n");
|
||||||
property.PropertySymbol.Type, property.Type, source, isFirstEntry);
|
source.Append(" [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]\n");
|
||||||
isFirstEntry = false;
|
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 (property.PropertySymbol.IsWriteOnly)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
GeneratePropertyGetter(property.PropertySymbol.Name,
|
||||||
|
property.PropertySymbol.Type, property.Type, source, isFirstEntry);
|
||||||
|
isFirstEntry = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
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");
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
// Generate GetGodotPropertyList
|
||||||
|
|
||||||
const string dictionaryType = "global::System.Collections.Generic.List<global::Godot.Bridge.PropertyInfo>";
|
const string dictionaryType = "global::System.Collections.Generic.List<global::Godot.Bridge.PropertyInfo>";
|
||||||
|
@ -119,8 +119,14 @@ namespace Godot.SourceGenerators
|
|||||||
.Where(s => !s.IsStatic && s.Kind == SymbolKind.Field && !s.IsImplicitlyDeclared)
|
.Where(s => !s.IsStatic && s.Kind == SymbolKind.Field && !s.IsImplicitlyDeclared)
|
||||||
.Cast<IFieldSymbol>();
|
.Cast<IFieldSymbol>();
|
||||||
|
|
||||||
var godotClassProperties = propertySymbols.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.
|
||||||
var godotClassFields = fieldSymbols.WhereIsGodotCompatibleType(typeCache).ToArray();
|
// 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
|
var signalDelegateSymbols = members
|
||||||
.Where(s => s.Kind == SymbolKind.NamedType)
|
.Where(s => s.Kind == SymbolKind.NamedType)
|
||||||
|
Loading…
Reference in New Issue
Block a user