Skip to content

Commit

Permalink
[C#] Enable nullability for variant classes
Browse files Browse the repository at this point in the history
  • Loading branch information
Repiteo committed Dec 9, 2023
1 parent b94eb58 commit 08e4412
Show file tree
Hide file tree
Showing 8 changed files with 62 additions and 43 deletions.
7 changes: 5 additions & 2 deletions modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
using System.Runtime.CompilerServices;
using Godot.NativeInterop;

#nullable enable

namespace Godot.Collections
{
/// <summary>
Expand All @@ -22,7 +24,7 @@ public sealed class Array :
{
internal godot_array.movable NativeValue;

private WeakReference<IDisposable> _weakReferenceToSelf;
private WeakReference<IDisposable>? _weakReferenceToSelf;

/// <summary>
/// Constructs a new empty <see cref="Array"/>.
Expand Down Expand Up @@ -1140,7 +1142,8 @@ internal static Array<T> CreateTakingOwnershipOfDisposableValue(godot_array nati
/// </summary>
/// <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>
public static explicit operator Array(Array<T> from)
[return: NotNullIfNotNull(nameof(from))]
public static explicit operator Array?(Array<T>? from)
{
return from?._underlyingArray;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ internal static unsafe void GetScriptNativeName(IntPtr scriptPtr, godot_string_n

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);

if (field == null)
Expand Down Expand Up @@ -253,11 +253,15 @@ internal static void SetGodotObjectPtr(IntPtr gcHandlePtr, IntPtr newPtr)
{
var editorAssembly = AppDomain.CurrentDomain.GetAssemblies()
.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);
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,7 @@ private static bool TryDeserializeSingleDelegate(byte[] buffer, [MaybeNullWhen(f
{
ulong objectId = reader.ReadUInt64();
// ReSharper disable once RedundantNameQualifier
GodotObject godotObject = GodotObject.InstanceFromId(objectId);
GodotObject? godotObject = GodotObject.InstanceFromId(objectId);
if (godotObject == null)
return false;

Expand Down
7 changes: 5 additions & 2 deletions modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
using System.Runtime.CompilerServices;
using Godot.NativeInterop;

#nullable enable

namespace Godot.Collections
{
/// <summary>
Expand All @@ -19,7 +21,7 @@ public sealed class Dictionary :
{
internal godot_dictionary.movable NativeValue;

private WeakReference<IDisposable> _weakReferenceToSelf;
private WeakReference<IDisposable>? _weakReferenceToSelf;

/// <summary>
/// Constructs a new empty <see cref="Dictionary"/>.
Expand Down Expand Up @@ -559,7 +561,8 @@ internal static Dictionary<TKey, TValue> CreateTakingOwnershipOfDisposableValue(
/// </summary>
/// <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>
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;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using System;
using Godot.NativeInterop;

#nullable enable

namespace Godot
{
public partial class GodotObject
Expand All @@ -26,7 +28,7 @@ public partial class GodotObject
/// </example>
/// <param name="instanceId">Instance ID of the Object to retrieve.</param>
/// <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));
}
Expand All @@ -49,7 +51,7 @@ public static bool IsInstanceIdValid(ulong id)
/// </summary>
/// <param name="instance">The instance to check.</param>
/// <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;
}
Expand All @@ -66,9 +68,9 @@ public static bool IsInstanceValid(GodotObject instance)
/// </summary>
/// <param name="obj">The object.</param>
/// <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>
public static WeakRef WeakRef(GodotObject obj)
public static WeakRef? WeakRef(GodotObject? obj)
{
if (!IsInstanceValid(obj))
return null;
Expand Down
23 changes: 11 additions & 12 deletions modules/mono/glue/GodotSharp/GodotSharp/Core/GodotObject.base.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using Godot.Bridge;
using Godot.NativeInterop;

#nullable enable

namespace Godot
{
public partial class GodotObject : IDisposable
Expand All @@ -13,7 +16,7 @@ public partial class GodotObject : IDisposable
internal IntPtr NativePtr;
private bool _memoryOwn;

private WeakReference<GodotObject> _weakReferenceToSelf;
private WeakReference<GodotObject>? _weakReferenceToSelf;

/// <summary>
/// Constructs a new <see cref="GodotObject"/>.
Expand Down Expand Up @@ -59,7 +62,7 @@ internal GodotObject(bool memoryOwn)
/// </summary>
public IntPtr NativeInstance => NativePtr;

internal static IntPtr GetPtr(GodotObject instance)
internal static IntPtr GetPtr(GodotObject? instance)
{
if (instance == null)
return IntPtr.Zero;
Expand Down Expand Up @@ -105,7 +108,7 @@ protected virtual void Dispose(bool disposing)

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
// it's associated to this managed instance, or if the target is no longer alive.
if (target != this && target != null)
Expand Down Expand Up @@ -176,18 +179,14 @@ public SignalAwaiter ToSignal(GodotObject source, StringName signal)

internal static Type InternalGetClassNativeBase(Type t)
{
do
{
var assemblyName = t.Assembly.GetName();
var name = t.Assembly.GetName().Name;

if (assemblyName.Name == "GodotSharp")
return t;
if (name == "GodotSharp" || name == "GodotSharpEditor")
return t;

if (assemblyName.Name == "GodotSharpEditor")
return t;
} while ((t = t.BaseType) != null);
Debug.Assert(t.BaseType is not null, "Script types must derive from a native Godot type.");

return null;
return InternalGetClassNativeBase(t.BaseType);
}

// ReSharper disable once VirtualMemberNeverOverridden.Global
Expand Down
18 changes: 11 additions & 7 deletions modules/mono/glue/GodotSharp/GodotSharp/Core/NodePath.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
using System;
using System.Diagnostics.CodeAnalysis;
using Godot.NativeInterop;

#nullable enable

namespace Godot
{
/// <summary>
Expand Down Expand Up @@ -39,11 +42,11 @@ namespace Godot
/// new NodePath("/root/MyAutoload"); // If you have an autoloaded node or scene.
/// </code>
/// </example>
public sealed class NodePath : IDisposable, IEquatable<NodePath>
public sealed class NodePath : IDisposable, IEquatable<NodePath?>
{
internal godot_node_path.movable NativeValue;

private WeakReference<IDisposable> _weakReferenceToSelf;
private WeakReference<IDisposable>? _weakReferenceToSelf;

~NodePath()
{
Expand Down Expand Up @@ -135,7 +138,8 @@ public NodePath(string path)
/// Converts this <see cref="NodePath"/> to a string.
/// </summary>
/// <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>
/// Converts this <see cref="NodePath"/> to a string.
Expand Down Expand Up @@ -289,19 +293,19 @@ public bool IsAbsolute()
/// <returns>If the <see cref="NodePath"/> is empty.</returns>
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)
return right is null;
return left.Equals(right);
}

public static bool operator !=(NodePath left, NodePath right)
public static bool operator !=(NodePath? left, NodePath? right)
{
return !(left == right);
}

public bool Equals(NodePath other)
public bool Equals([NotNullWhen(true)] NodePath? other)
{
if (other is null)
return false;
Expand All @@ -310,7 +314,7 @@ public bool Equals(NodePath other)
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));
}
Expand Down
26 changes: 15 additions & 11 deletions modules/mono/glue/GodotSharp/GodotSharp/Core/StringName.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
using System;
using System.Diagnostics.CodeAnalysis;
using Godot.NativeInterop;

#nullable enable

namespace Godot
{
/// <summary>
Expand All @@ -10,11 +13,11 @@ namespace Godot
/// Comparing them is much faster than with regular strings, because only the pointers are compared,
/// not the whole strings.
/// </summary>
public sealed class StringName : IDisposable, IEquatable<StringName>
public sealed class StringName : IDisposable, IEquatable<StringName?>
{
internal godot_string_name.movable NativeValue;

private WeakReference<IDisposable> _weakReferenceToSelf;
private WeakReference<IDisposable>? _weakReferenceToSelf;

~StringName()
{
Expand Down Expand Up @@ -81,7 +84,8 @@ public StringName(string name)
/// Converts a <see cref="StringName"/> to a string.
/// </summary>
/// <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>
/// Converts this <see cref="StringName"/> to a string.
Expand All @@ -104,43 +108,43 @@ public override string ToString()
/// <returns>If the <see cref="StringName"/> is empty.</returns>
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)
return right is null;
return left.Equals(right);
}

public static bool operator !=(StringName left, StringName right)
public static bool operator !=(StringName? left, StringName? right)
{
return !(left == right);
}

public bool Equals(StringName other)
public bool Equals([NotNullWhen(true)] StringName? other)
{
if (other is null)
return false;
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)
return right.IsEmpty;
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);
}

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;
}

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);
}
Expand All @@ -150,7 +154,7 @@ public bool Equals(in godot_string_name 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));
}
Expand Down

0 comments on commit 08e4412

Please sign in to comment.