Merge pull request #119746 from raulsntos/dotnet/ignore-member-attribute

[.NET] Add `IgnoreMember` attribute to exclude members from Godot
This commit is contained in:
Thaddeus Crews
2026-06-22 08:29:46 -05:00
14 changed files with 73 additions and 3 deletions
@@ -253,6 +253,10 @@ partial class ExportedFields
/// </summary>
public new static readonly global::Godot.StringName @_fieldGodotGenericArray = "_fieldGodotGenericArray";
/// <summary>
/// Cached name for the '_notIgnoredField' field.
/// </summary>
public new static readonly global::Godot.StringName @_notIgnoredField = "_notIgnoredField";
/// <summary>
/// Cached name for the '_fieldEmptyInt64Array' field.
/// </summary>
public new static readonly global::Godot.StringName @_fieldEmptyInt64Array = "_fieldEmptyInt64Array";
@@ -505,6 +509,10 @@ partial class ExportedFields
this.@_fieldGodotGenericArray = global::Godot.NativeInterop.VariantUtils.ConvertToArray<int>(value);
return true;
}
if (name == PropertyName.@_notIgnoredField) {
this.@_notIgnoredField = global::Godot.NativeInterop.VariantUtils.ConvertTo<int>(value);
return true;
}
if (name == PropertyName.@_fieldEmptyInt64Array) {
this.@_fieldEmptyInt64Array = global::Godot.NativeInterop.VariantUtils.ConvertTo<long[]>(value);
return true;
@@ -759,6 +767,10 @@ partial class ExportedFields
value = global::Godot.NativeInterop.VariantUtils.CreateFromArray(this.@_fieldGodotGenericArray);
return true;
}
if (name == PropertyName.@_notIgnoredField) {
value = global::Godot.NativeInterop.VariantUtils.CreateFrom<int>(this.@_notIgnoredField);
return true;
}
if (name == PropertyName.@_fieldEmptyInt64Array) {
value = global::Godot.NativeInterop.VariantUtils.CreateFrom<long[]>(this.@_fieldEmptyInt64Array);
return true;
@@ -835,6 +847,7 @@ partial class ExportedFields
properties.Add(new(type: (global::Godot.Variant.Type)28, name: PropertyName.@_fieldGodotArray, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
properties.Add(new(type: (global::Godot.Variant.Type)27, name: PropertyName.@_fieldGodotGenericDictionary, hint: (global::Godot.PropertyHint)23, hintString: "4/0:;1/0:", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
properties.Add(new(type: (global::Godot.Variant.Type)28, name: PropertyName.@_fieldGodotGenericArray, hint: (global::Godot.PropertyHint)23, hintString: "2/0:", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
properties.Add(new(type: (global::Godot.Variant.Type)2, name: PropertyName.@_notIgnoredField, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4096, exported: false));
properties.Add(new(type: (global::Godot.Variant.Type)31, name: PropertyName.@_fieldEmptyInt64Array, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
return properties;
}
@@ -293,6 +293,10 @@ partial class ExportedProperties
/// </summary>
public new static readonly global::Godot.StringName @PropertyGodotGenericArray = "PropertyGodotGenericArray";
/// <summary>
/// Cached name for the 'NotIgnoredProperty' property.
/// </summary>
public new static readonly global::Godot.StringName @NotIgnoredProperty = "NotIgnoredProperty";
/// <summary>
/// Cached name for the '_notGeneratePropertyString' field.
/// </summary>
public new static readonly global::Godot.StringName @_notGeneratePropertyString = "_notGeneratePropertyString";
@@ -609,6 +613,10 @@ partial class ExportedProperties
this.@PropertyGodotGenericArray = global::Godot.NativeInterop.VariantUtils.ConvertToArray<int>(value);
return true;
}
if (name == PropertyName.@NotIgnoredProperty) {
this.@NotIgnoredProperty = global::Godot.NativeInterop.VariantUtils.ConvertTo<int>(value);
return true;
}
if (name == PropertyName.@_notGeneratePropertyString) {
this.@_notGeneratePropertyString = global::Godot.NativeInterop.VariantUtils.ConvertTo<string>(value);
return true;
@@ -927,6 +935,10 @@ partial class ExportedProperties
value = global::Godot.NativeInterop.VariantUtils.CreateFromArray(this.@PropertyGodotGenericArray);
return true;
}
if (name == PropertyName.@NotIgnoredProperty) {
value = global::Godot.NativeInterop.VariantUtils.CreateFrom<int>(this.@NotIgnoredProperty);
return true;
}
if (name == PropertyName.@_notGeneratePropertyString) {
value = global::Godot.NativeInterop.VariantUtils.CreateFrom<string>(this.@_notGeneratePropertyString);
return true;
@@ -1044,6 +1056,7 @@ partial class ExportedProperties
properties.Add(new(type: (global::Godot.Variant.Type)28, name: PropertyName.@PropertyGodotArray, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
properties.Add(new(type: (global::Godot.Variant.Type)27, name: PropertyName.@PropertyGodotGenericDictionary, hint: (global::Godot.PropertyHint)23, hintString: "4/0:;1/0:", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
properties.Add(new(type: (global::Godot.Variant.Type)28, name: PropertyName.@PropertyGodotGenericArray, hint: (global::Godot.PropertyHint)23, hintString: "2/0:", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
properties.Add(new(type: (global::Godot.Variant.Type)2, name: PropertyName.@NotIgnoredProperty, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4096, exported: false));
return properties;
}
#pragma warning restore CS0109
@@ -104,4 +104,9 @@ public partial class ExportedFields : GodotObject
[Export]
private Godot.Collections.Array<int> _fieldGodotGenericArray = new() { 0, 1, 2, 3, 4, 5, 6 };
private int _notIgnoredField;
[IgnoreMember]
private int _ignoredField;
}
@@ -223,4 +223,9 @@ public partial class ExportedProperties(string primaryCtorParameter) : GodotObje
[Export]
private Godot.Collections.Array<int> PropertyGodotGenericArray { get; set; } = new() { 0, 1, 2, 3, 4, 5, 6 };
public int NotIgnoredProperty { get; set; }
[IgnoreMember]
public int IgnoredProperty { get; set; }
}
@@ -2,6 +2,11 @@ using Godot;
public partial class Methods : GodotObject
{
[IgnoreMember]
private void IgnoredMethod()
{
}
private void MethodWithOverload()
{
}
@@ -5,6 +5,12 @@ public partial class ScriptBoilerplate : Node
private NodePath _nodePath;
private int _velocity;
[IgnoreMember]
private int _ignoredField;
[IgnoreMember]
private int IgnoredProperty { get; set; }
public override void _Process(double delta)
{
_ = delta;
@@ -299,6 +299,9 @@ namespace Godot.SourceGenerators
public static bool IsSystemFlagsAttribute(this INamedTypeSymbol symbol)
=> symbol.FullQualifiedNameOmitGlobal() == GodotClasses.SystemFlagsAttr;
public static bool IsGodotIgnoreMemberAttribute(this INamedTypeSymbol symbol)
=> symbol.FullQualifiedNameOmitGlobal() == GodotClasses.IgnoreMemberAttr;
public static GodotMethodData? HasGodotCompatibleSignature(
this IMethodSymbol method,
MarshalUtils.TypeCache typeCache
@@ -11,6 +11,7 @@ namespace Godot.SourceGenerators
public const string ExportGroupAttr = "Godot.ExportGroupAttribute";
public const string ExportSubgroupAttr = "Godot.ExportSubgroupAttribute";
public const string ExportToolButtonAttr = "Godot.ExportToolButtonAttribute";
public const string IgnoreMemberAttr = "Godot.IgnoreMemberAttribute";
public const string SignalAttr = "Godot.SignalAttribute";
public const string MustBeVariantAttr = "Godot.MustBeVariantAttribute";
public const string GodotClassNameAttr = "Godot.GodotClassNameAttribute";
@@ -128,6 +128,8 @@ namespace Godot.SourceGenerators
var methodSymbols = members
.Where(s => s.Kind == SymbolKind.Method && !s.IsImplicitlyDeclared)
.Cast<IMethodSymbol>()
.Where(m => !m.GetAttributes()
.Any(a => a.AttributeClass?.IsGodotIgnoreMemberAttribute() ?? false))
.Where(m => m.MethodKind == MethodKind.Ordinary);
var godotClassMethods = methodSymbols.WhereHasGodotCompatibleSignature(typeCache)
@@ -112,7 +112,9 @@ namespace Godot.SourceGenerators
source.Append(symbol.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat));
source.Append("\n{\n");
var members = symbol.GetMembers();
var members = symbol.GetMembers()
.Where(m => !m.GetAttributes()
.Any(a => a.AttributeClass?.IsGodotIgnoreMemberAttribute() ?? false));
var propertySymbols = members
.Where(s => !s.IsStatic && s.Kind == SymbolKind.Property)
@@ -111,7 +111,9 @@ namespace Godot.SourceGenerators
var exportedMembers = new List<ExportedPropertyMetadata>();
var members = symbol.GetMembers();
var members = symbol.GetMembers()
.Where(m => !m.GetAttributes()
.Any(a => a.AttributeClass?.IsGodotIgnoreMemberAttribute() ?? false));
var exportedProperties = members
.Where(s => s.Kind == SymbolKind.Property)
@@ -110,7 +110,9 @@ namespace Godot.SourceGenerators
source.Append(symbol.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat));
source.Append("\n{\n");
var members = symbol.GetMembers();
var members = symbol.GetMembers()
.Where(m => !m.GetAttributes()
.Any(a => a.AttributeClass?.IsGodotIgnoreMemberAttribute() ?? false));
var propertySymbols = members
.Where(s => !s.IsStatic && s.Kind == SymbolKind.Property)
@@ -0,0 +1,10 @@
using System;
namespace Godot
{
/// <summary>
/// An attribute that excludes a member from registering as a method or property in Godot.
/// </summary>
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field)]
public sealed class IgnoreMemberAttribute : Attribute { }
}
@@ -74,6 +74,7 @@
<Compile Include="Core\Attributes\ScriptPathAttribute.cs" />
<Compile Include="Core\Attributes\SignalAttribute.cs" />
<Compile Include="Core\Attributes\ToolAttribute.cs" />
<Compile Include="Core\Attributes\IgnoreMemberAttribute.cs" />
<Compile Include="Core\Basis.cs" />
<Compile Include="Core\Bridge\CSharpInstanceBridge.cs" />
<Compile Include="Core\Bridge\GCHandleBridge.cs" />