Merge pull request #82983 from Repiteo/c#-godotsharp-nullable-classes
[C#] Enable nullability for variant classes
This commit is contained in:
commit
ef79e5d9dd
8 changed files with 62 additions and 43 deletions
|
@ -6,6 +6,8 @@ using System.Linq;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using Godot.NativeInterop;
|
using Godot.NativeInterop;
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
|
||||||
namespace Godot.Collections
|
namespace Godot.Collections
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -22,7 +24,7 @@ namespace Godot.Collections
|
||||||
{
|
{
|
||||||
internal godot_array.movable NativeValue;
|
internal godot_array.movable NativeValue;
|
||||||
|
|
||||||
private WeakReference<IDisposable> _weakReferenceToSelf;
|
private WeakReference<IDisposable>? _weakReferenceToSelf;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructs a new empty <see cref="Array"/>.
|
/// Constructs a new empty <see cref="Array"/>.
|
||||||
|
@ -1140,7 +1142,8 @@ namespace Godot.Collections
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="from">The typed array to convert.</param>
|
/// <param name="from">The typed array to convert.</param>
|
||||||
/// <returns>A new Godot Array, or <see langword="null"/> if <see paramref="from"/> was null.</returns>
|
/// <returns>A new Godot Array, or <see langword="null"/> if <see paramref="from"/> was null.</returns>
|
||||||
public static explicit operator Array(Array<T> from)
|
[return: NotNullIfNotNull(nameof(from))]
|
||||||
|
public static explicit operator Array?(Array<T>? from)
|
||||||
{
|
{
|
||||||
return from?._underlyingArray;
|
return from?._underlyingArray;
|
||||||
}
|
}
|
||||||
|
|
|
@ -194,7 +194,7 @@ namespace Godot.Bridge
|
||||||
|
|
||||||
var native = GodotObject.InternalGetClassNativeBase(scriptType);
|
var native = GodotObject.InternalGetClassNativeBase(scriptType);
|
||||||
|
|
||||||
var field = native?.GetField("NativeName", BindingFlags.DeclaredOnly | BindingFlags.Static |
|
var field = native.GetField("NativeName", BindingFlags.DeclaredOnly | BindingFlags.Static |
|
||||||
BindingFlags.Public | BindingFlags.NonPublic);
|
BindingFlags.Public | BindingFlags.NonPublic);
|
||||||
|
|
||||||
if (field == null)
|
if (field == null)
|
||||||
|
@ -253,11 +253,15 @@ namespace Godot.Bridge
|
||||||
{
|
{
|
||||||
var editorAssembly = AppDomain.CurrentDomain.GetAssemblies()
|
var editorAssembly = AppDomain.CurrentDomain.GetAssemblies()
|
||||||
.FirstOrDefault(a => a.GetName().Name == "GodotSharpEditor");
|
.FirstOrDefault(a => a.GetName().Name == "GodotSharpEditor");
|
||||||
wrapperType = editorAssembly?.GetType("Godot." + nativeTypeNameStr);
|
|
||||||
|
|
||||||
if (wrapperType == null)
|
if (editorAssembly != null)
|
||||||
{
|
{
|
||||||
wrapperType = GetTypeByGodotClassAttr(editorAssembly, nativeTypeNameStr);
|
wrapperType = editorAssembly.GetType("Godot." + nativeTypeNameStr);
|
||||||
|
|
||||||
|
if (wrapperType == null)
|
||||||
|
{
|
||||||
|
wrapperType = GetTypeByGodotClassAttr(editorAssembly, nativeTypeNameStr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -414,7 +414,7 @@ namespace Godot
|
||||||
{
|
{
|
||||||
ulong objectId = reader.ReadUInt64();
|
ulong objectId = reader.ReadUInt64();
|
||||||
// ReSharper disable once RedundantNameQualifier
|
// ReSharper disable once RedundantNameQualifier
|
||||||
GodotObject godotObject = GodotObject.InstanceFromId(objectId);
|
GodotObject? godotObject = GodotObject.InstanceFromId(objectId);
|
||||||
if (godotObject == null)
|
if (godotObject == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,8 @@ using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using Godot.NativeInterop;
|
using Godot.NativeInterop;
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
|
||||||
namespace Godot.Collections
|
namespace Godot.Collections
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -19,7 +21,7 @@ namespace Godot.Collections
|
||||||
{
|
{
|
||||||
internal godot_dictionary.movable NativeValue;
|
internal godot_dictionary.movable NativeValue;
|
||||||
|
|
||||||
private WeakReference<IDisposable> _weakReferenceToSelf;
|
private WeakReference<IDisposable>? _weakReferenceToSelf;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructs a new empty <see cref="Dictionary"/>.
|
/// Constructs a new empty <see cref="Dictionary"/>.
|
||||||
|
@ -559,7 +561,8 @@ namespace Godot.Collections
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="from">The typed dictionary to convert.</param>
|
/// <param name="from">The typed dictionary to convert.</param>
|
||||||
/// <returns>A new Godot Dictionary, or <see langword="null"/> if <see paramref="from"/> was null.</returns>
|
/// <returns>A new Godot Dictionary, or <see langword="null"/> if <see paramref="from"/> was null.</returns>
|
||||||
public static explicit operator Dictionary(Dictionary<TKey, TValue> from)
|
[return: NotNullIfNotNull(nameof(from))]
|
||||||
|
public static explicit operator Dictionary?(Dictionary<TKey, TValue>? from)
|
||||||
{
|
{
|
||||||
return from?._underlyingDict;
|
return from?._underlyingDict;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
using System;
|
using System;
|
||||||
using Godot.NativeInterop;
|
using Godot.NativeInterop;
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
|
||||||
namespace Godot
|
namespace Godot
|
||||||
{
|
{
|
||||||
public partial class GodotObject
|
public partial class GodotObject
|
||||||
|
@ -26,7 +28,7 @@ namespace Godot
|
||||||
/// </example>
|
/// </example>
|
||||||
/// <param name="instanceId">Instance ID of the Object to retrieve.</param>
|
/// <param name="instanceId">Instance ID of the Object to retrieve.</param>
|
||||||
/// <returns>The <see cref="GodotObject"/> instance.</returns>
|
/// <returns>The <see cref="GodotObject"/> instance.</returns>
|
||||||
public static GodotObject InstanceFromId(ulong instanceId)
|
public static GodotObject? InstanceFromId(ulong instanceId)
|
||||||
{
|
{
|
||||||
return InteropUtils.UnmanagedGetManaged(NativeFuncs.godotsharp_instance_from_id(instanceId));
|
return InteropUtils.UnmanagedGetManaged(NativeFuncs.godotsharp_instance_from_id(instanceId));
|
||||||
}
|
}
|
||||||
|
@ -49,7 +51,7 @@ namespace Godot
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="instance">The instance to check.</param>
|
/// <param name="instance">The instance to check.</param>
|
||||||
/// <returns>If the instance is a valid object.</returns>
|
/// <returns>If the instance is a valid object.</returns>
|
||||||
public static bool IsInstanceValid(GodotObject instance)
|
public static bool IsInstanceValid(GodotObject? instance)
|
||||||
{
|
{
|
||||||
return instance != null && instance.NativeInstance != IntPtr.Zero;
|
return instance != null && instance.NativeInstance != IntPtr.Zero;
|
||||||
}
|
}
|
||||||
|
@ -66,9 +68,9 @@ namespace Godot
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="obj">The object.</param>
|
/// <param name="obj">The object.</param>
|
||||||
/// <returns>
|
/// <returns>
|
||||||
/// The <see cref="WeakRef"/> reference to the object or <see langword="null"/>.
|
/// The <see cref="Godot.WeakRef"/> reference to the object or <see langword="null"/>.
|
||||||
/// </returns>
|
/// </returns>
|
||||||
public static WeakRef WeakRef(GodotObject obj)
|
public static WeakRef? WeakRef(GodotObject? obj)
|
||||||
{
|
{
|
||||||
if (!IsInstanceValid(obj))
|
if (!IsInstanceValid(obj))
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using Godot.Bridge;
|
using Godot.Bridge;
|
||||||
using Godot.NativeInterop;
|
using Godot.NativeInterop;
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
|
||||||
namespace Godot
|
namespace Godot
|
||||||
{
|
{
|
||||||
public partial class GodotObject : IDisposable
|
public partial class GodotObject : IDisposable
|
||||||
|
@ -13,7 +16,7 @@ namespace Godot
|
||||||
internal IntPtr NativePtr;
|
internal IntPtr NativePtr;
|
||||||
private bool _memoryOwn;
|
private bool _memoryOwn;
|
||||||
|
|
||||||
private WeakReference<GodotObject> _weakReferenceToSelf;
|
private WeakReference<GodotObject>? _weakReferenceToSelf;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructs a new <see cref="GodotObject"/>.
|
/// Constructs a new <see cref="GodotObject"/>.
|
||||||
|
@ -59,7 +62,7 @@ namespace Godot
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IntPtr NativeInstance => NativePtr;
|
public IntPtr NativeInstance => NativePtr;
|
||||||
|
|
||||||
internal static IntPtr GetPtr(GodotObject instance)
|
internal static IntPtr GetPtr(GodotObject? instance)
|
||||||
{
|
{
|
||||||
if (instance == null)
|
if (instance == null)
|
||||||
return IntPtr.Zero;
|
return IntPtr.Zero;
|
||||||
|
@ -105,7 +108,7 @@ namespace Godot
|
||||||
|
|
||||||
if (gcHandleToFree != IntPtr.Zero)
|
if (gcHandleToFree != IntPtr.Zero)
|
||||||
{
|
{
|
||||||
object target = GCHandle.FromIntPtr(gcHandleToFree).Target;
|
object? target = GCHandle.FromIntPtr(gcHandleToFree).Target;
|
||||||
// The GC handle may have been replaced in another thread. Release it only if
|
// The GC handle may have been replaced in another thread. Release it only if
|
||||||
// it's associated to this managed instance, or if the target is no longer alive.
|
// it's associated to this managed instance, or if the target is no longer alive.
|
||||||
if (target != this && target != null)
|
if (target != this && target != null)
|
||||||
|
@ -176,18 +179,14 @@ namespace Godot
|
||||||
|
|
||||||
internal static Type InternalGetClassNativeBase(Type t)
|
internal static Type InternalGetClassNativeBase(Type t)
|
||||||
{
|
{
|
||||||
do
|
var name = t.Assembly.GetName().Name;
|
||||||
{
|
|
||||||
var assemblyName = t.Assembly.GetName();
|
|
||||||
|
|
||||||
if (assemblyName.Name == "GodotSharp")
|
if (name == "GodotSharp" || name == "GodotSharpEditor")
|
||||||
return t;
|
return t;
|
||||||
|
|
||||||
if (assemblyName.Name == "GodotSharpEditor")
|
Debug.Assert(t.BaseType is not null, "Script types must derive from a native Godot type.");
|
||||||
return t;
|
|
||||||
} while ((t = t.BaseType) != null);
|
|
||||||
|
|
||||||
return null;
|
return InternalGetClassNativeBase(t.BaseType);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReSharper disable once VirtualMemberNeverOverridden.Global
|
// ReSharper disable once VirtualMemberNeverOverridden.Global
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using Godot.NativeInterop;
|
using Godot.NativeInterop;
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
|
||||||
namespace Godot
|
namespace Godot
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -39,11 +42,11 @@ namespace Godot
|
||||||
/// new NodePath("/root/MyAutoload"); // If you have an autoloaded node or scene.
|
/// new NodePath("/root/MyAutoload"); // If you have an autoloaded node or scene.
|
||||||
/// </code>
|
/// </code>
|
||||||
/// </example>
|
/// </example>
|
||||||
public sealed class NodePath : IDisposable, IEquatable<NodePath>
|
public sealed class NodePath : IDisposable, IEquatable<NodePath?>
|
||||||
{
|
{
|
||||||
internal godot_node_path.movable NativeValue;
|
internal godot_node_path.movable NativeValue;
|
||||||
|
|
||||||
private WeakReference<IDisposable> _weakReferenceToSelf;
|
private WeakReference<IDisposable>? _weakReferenceToSelf;
|
||||||
|
|
||||||
~NodePath()
|
~NodePath()
|
||||||
{
|
{
|
||||||
|
@ -135,7 +138,8 @@ namespace Godot
|
||||||
/// Converts this <see cref="NodePath"/> to a string.
|
/// Converts this <see cref="NodePath"/> to a string.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="from">The <see cref="NodePath"/> to convert.</param>
|
/// <param name="from">The <see cref="NodePath"/> to convert.</param>
|
||||||
public static implicit operator string(NodePath from) => from?.ToString();
|
[return: NotNullIfNotNull(nameof(from))]
|
||||||
|
public static implicit operator string?(NodePath? from) => from?.ToString();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Converts this <see cref="NodePath"/> to a string.
|
/// Converts this <see cref="NodePath"/> to a string.
|
||||||
|
@ -289,19 +293,19 @@ namespace Godot
|
||||||
/// <returns>If the <see cref="NodePath"/> is empty.</returns>
|
/// <returns>If the <see cref="NodePath"/> is empty.</returns>
|
||||||
public bool IsEmpty => NativeValue.DangerousSelfRef.IsEmpty;
|
public bool IsEmpty => NativeValue.DangerousSelfRef.IsEmpty;
|
||||||
|
|
||||||
public static bool operator ==(NodePath left, NodePath right)
|
public static bool operator ==(NodePath? left, NodePath? right)
|
||||||
{
|
{
|
||||||
if (left is null)
|
if (left is null)
|
||||||
return right is null;
|
return right is null;
|
||||||
return left.Equals(right);
|
return left.Equals(right);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool operator !=(NodePath left, NodePath right)
|
public static bool operator !=(NodePath? left, NodePath? right)
|
||||||
{
|
{
|
||||||
return !(left == right);
|
return !(left == right);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Equals(NodePath other)
|
public bool Equals([NotNullWhen(true)] NodePath? other)
|
||||||
{
|
{
|
||||||
if (other is null)
|
if (other is null)
|
||||||
return false;
|
return false;
|
||||||
|
@ -310,7 +314,7 @@ namespace Godot
|
||||||
return NativeFuncs.godotsharp_node_path_equals(self, otherNative).ToBool();
|
return NativeFuncs.godotsharp_node_path_equals(self, otherNative).ToBool();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Equals(object obj)
|
public override bool Equals([NotNullWhen(true)] object? obj)
|
||||||
{
|
{
|
||||||
return ReferenceEquals(this, obj) || (obj is NodePath other && Equals(other));
|
return ReferenceEquals(this, obj) || (obj is NodePath other && Equals(other));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using Godot.NativeInterop;
|
using Godot.NativeInterop;
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
|
||||||
namespace Godot
|
namespace Godot
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -10,11 +13,11 @@ namespace Godot
|
||||||
/// Comparing them is much faster than with regular strings, because only the pointers are compared,
|
/// Comparing them is much faster than with regular strings, because only the pointers are compared,
|
||||||
/// not the whole strings.
|
/// not the whole strings.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class StringName : IDisposable, IEquatable<StringName>
|
public sealed class StringName : IDisposable, IEquatable<StringName?>
|
||||||
{
|
{
|
||||||
internal godot_string_name.movable NativeValue;
|
internal godot_string_name.movable NativeValue;
|
||||||
|
|
||||||
private WeakReference<IDisposable> _weakReferenceToSelf;
|
private WeakReference<IDisposable>? _weakReferenceToSelf;
|
||||||
|
|
||||||
~StringName()
|
~StringName()
|
||||||
{
|
{
|
||||||
|
@ -81,7 +84,8 @@ namespace Godot
|
||||||
/// Converts a <see cref="StringName"/> to a string.
|
/// Converts a <see cref="StringName"/> to a string.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="from">The <see cref="StringName"/> to convert.</param>
|
/// <param name="from">The <see cref="StringName"/> to convert.</param>
|
||||||
public static implicit operator string(StringName from) => from?.ToString();
|
[return: NotNullIfNotNull(nameof(from))]
|
||||||
|
public static implicit operator string?(StringName? from) => from?.ToString();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Converts this <see cref="StringName"/> to a string.
|
/// Converts this <see cref="StringName"/> to a string.
|
||||||
|
@ -104,43 +108,43 @@ namespace Godot
|
||||||
/// <returns>If the <see cref="StringName"/> is empty.</returns>
|
/// <returns>If the <see cref="StringName"/> is empty.</returns>
|
||||||
public bool IsEmpty => NativeValue.DangerousSelfRef.IsEmpty;
|
public bool IsEmpty => NativeValue.DangerousSelfRef.IsEmpty;
|
||||||
|
|
||||||
public static bool operator ==(StringName left, StringName right)
|
public static bool operator ==(StringName? left, StringName? right)
|
||||||
{
|
{
|
||||||
if (left is null)
|
if (left is null)
|
||||||
return right is null;
|
return right is null;
|
||||||
return left.Equals(right);
|
return left.Equals(right);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool operator !=(StringName left, StringName right)
|
public static bool operator !=(StringName? left, StringName? right)
|
||||||
{
|
{
|
||||||
return !(left == right);
|
return !(left == right);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Equals(StringName other)
|
public bool Equals([NotNullWhen(true)] StringName? other)
|
||||||
{
|
{
|
||||||
if (other is null)
|
if (other is null)
|
||||||
return false;
|
return false;
|
||||||
return NativeValue.DangerousSelfRef == other.NativeValue.DangerousSelfRef;
|
return NativeValue.DangerousSelfRef == other.NativeValue.DangerousSelfRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool operator ==(StringName left, in godot_string_name right)
|
public static bool operator ==(StringName? left, in godot_string_name right)
|
||||||
{
|
{
|
||||||
if (left is null)
|
if (left is null)
|
||||||
return right.IsEmpty;
|
return right.IsEmpty;
|
||||||
return left.Equals(right);
|
return left.Equals(right);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool operator !=(StringName left, in godot_string_name right)
|
public static bool operator !=(StringName? left, in godot_string_name right)
|
||||||
{
|
{
|
||||||
return !(left == right);
|
return !(left == right);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool operator ==(in godot_string_name left, StringName right)
|
public static bool operator ==(in godot_string_name left, StringName? right)
|
||||||
{
|
{
|
||||||
return right == left;
|
return right == left;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool operator !=(in godot_string_name left, StringName right)
|
public static bool operator !=(in godot_string_name left, StringName? right)
|
||||||
{
|
{
|
||||||
return !(right == left);
|
return !(right == left);
|
||||||
}
|
}
|
||||||
|
@ -150,7 +154,7 @@ namespace Godot
|
||||||
return NativeValue.DangerousSelfRef == other;
|
return NativeValue.DangerousSelfRef == other;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Equals(object obj)
|
public override bool Equals([NotNullWhen(true)] object? obj)
|
||||||
{
|
{
|
||||||
return ReferenceEquals(this, obj) || (obj is StringName other && Equals(other));
|
return ReferenceEquals(this, obj) || (obj is StringName other && Equals(other));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue