diff --git a/PKHeX.Core/Editing/Bulk/BatchEditing.cs b/PKHeX.Core/Editing/Bulk/BatchEditing.cs
index 693c7a9a4..4be210e95 100644
--- a/PKHeX.Core/Editing/Bulk/BatchEditing.cs
+++ b/PKHeX.Core/Editing/Bulk/BatchEditing.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Linq;
using System.Reflection;
@@ -68,12 +69,46 @@ private static string[][] GetPropArray()
/// Property Name to check
/// Property Info retrieved (if any).
/// True if has property, false if does not.
- public static bool TryGetHasProperty(PKM pk, string name, out PropertyInfo pi)
+ public static bool TryGetHasProperty(PKM pk, string name, [NotNullWhen(true)] out PropertyInfo? pi)
{
- var props = Props[Array.IndexOf(Types, pk.GetType())];
+ var type = pk.GetType();
+ return TryGetHasProperty(type, name, out pi);
+ }
+
+ ///
+ /// Tries to fetch the property from the cache of available properties.
+ ///
+ /// Type to check
+ /// Property Name to check
+ /// Property Info retrieved (if any).
+ /// True if has property, false if does not.
+ public static bool TryGetHasProperty(Type type, string name, [NotNullWhen(true)] out PropertyInfo? pi)
+ {
+ var index = Array.IndexOf(Types, type);
+ if (index < 0)
+ {
+ pi = null;
+ return false;
+ }
+ var props = Props[index];
return props.TryGetValue(name, out pi);
}
+ ///
+ /// Gets a list of types that implement the requested .
+ ///
+ public static IEnumerable GetTypesImplementing(string property)
+ {
+ for (int i = 0; i < Types.Length; i++)
+ {
+ var type = Types[i];
+ var props = Props[i];
+ if (!props.TryGetValue(property, out var pi))
+ continue;
+ yield return $"{type.Name}: {pi.PropertyType.Name}";
+ }
+ }
+
///
/// Gets the type of the property using the saved cache of properties.
///
@@ -160,8 +195,6 @@ public static bool IsFilterMatch(IEnumerable filters, object
return false;
try
{
- if (pi == null)
- continue;
if (pi.IsValueEqual(obj, cmd.PropertyValue) == cmd.Evaluator)
continue;
}
diff --git a/PKHeX.Core/PKM/PKM.cs b/PKHeX.Core/PKM/PKM.cs
index 7b9f6d5ab..e7acbb60e 100644
--- a/PKHeX.Core/PKM/PKM.cs
+++ b/PKHeX.Core/PKM/PKM.cs
@@ -1053,7 +1053,8 @@ public void TransferPropertiesWithReflection(PKM Destination)
var shared = destProperties.Intersect(srcProperties);
foreach (string property in shared)
{
- BatchEditing.TryGetHasProperty(this, property, out var src);
+ if (!BatchEditing.TryGetHasProperty(this, property, out var src))
+ continue;
var prop = src.GetValue(this);
if (prop is not byte[] && BatchEditing.TryGetHasProperty(Destination, property, out var pi))
ReflectUtil.SetValue(pi, Destination, prop);
diff --git a/PKHeX.Core/PKM/Util/PKMConverter.cs b/PKHeX.Core/PKM/Util/PKMConverter.cs
index f37f7bd0a..ec95ebce2 100644
--- a/PKHeX.Core/PKM/Util/PKMConverter.cs
+++ b/PKHeX.Core/PKM/Util/PKMConverter.cs
@@ -286,17 +286,19 @@ public static bool IsConvertibleToFormat(PKM pk, int format)
// Sequential
case PK1 pk1: return pk1.ConvertToPK2();
case PK2 pk2: return pk2.ConvertToPK1();
- case SK2 sk2: return sk2.ConvertToPK2();
- case CK3 ck3: return ck3.ConvertToPK3();
- case XK3 xk3: return xk3.ConvertToPK3();
case PK3 pk3: return pk3.ConvertToPK4();
- case BK4 bk4: return bk4.ConvertToPK4();
case PK4 pk4: return pk4.ConvertToPK5();
case PK5 pk5: return pk5.ConvertToPK6();
case PK6 pk6: return pk6.ConvertToPK7();
case PK7 pk7: return pk7.ConvertToPK8();
case PB7 pb7: return pb7.ConvertToPK8();
+ // Side-Formats back to Mainline
+ case SK2 sk2: return sk2.ConvertToPK2();
+ case CK3 ck3: return ck3.ConvertToPK3();
+ case XK3 xk3: return xk3.ConvertToPK3();
+ case BK4 bk4: return bk4.ConvertToPK4();
+
// None
default:
comment = MsgPKMConvertFailNoMethod;
@@ -312,18 +314,17 @@ public static bool IsConvertibleToFormat(PKM pk, int format)
/// Indication if Not Transferable
private static bool IsNotTransferable(PKM pk, out string comment)
{
- switch (pk.Species)
+ switch (pk)
{
+ case PK4 { Species: (int)Species.Pichu } pk4 when pk4.Form != 0:
+ case PK6 { Species: (int)Species.Pikachu } pk6 when pk6.Form != 0:
+ case PB7 { Species: (int)Species.Pikachu } pika when pika.Form != 0:
+ case PB7 { Species: (int)Species.Eevee } eevee when eevee.Form != 0:
+ comment = MsgPKMConvertFailForm;
+ return true;
default:
comment = string.Empty;
return false;
-
- case 025 when pk.Form != 0 && pk.Gen6: // Cosplay Pikachu
- case 172 when pk.Form != 0 && pk.Gen4: // Spiky Eared Pichu
- case 025 when pk.Form == 8 && pk.LGPE: // Buddy Pikachu
- case 133 when pk.Form == 1 && pk.LGPE: // Buddy Eevee
- comment = MsgPKMConvertFailForm;
- return true;
}
}
diff --git a/PKHeX.Core/Util/FileUtil.cs b/PKHeX.Core/Util/FileUtil.cs
index a4ac4c02c..4ab7aa625 100644
--- a/PKHeX.Core/Util/FileUtil.cs
+++ b/PKHeX.Core/Util/FileUtil.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using System.IO;
namespace PKHeX.Core
@@ -89,7 +90,7 @@ public static int GetFileSize(string path)
#pragma warning restore CA1031 // Do not catch general exception types
}
- private static bool TryGetGP1(byte[] data, out GP1? gp1)
+ private static bool TryGetGP1(byte[] data, [NotNullWhen(true)] out GP1? gp1)
{
gp1 = null;
if (data.Length != GP1.SIZE || BitConverter.ToUInt32(data, 0x28) == 0)
@@ -98,7 +99,7 @@ private static bool TryGetGP1(byte[] data, out GP1? gp1)
return true;
}
- private static bool TryGetBundle(byte[] data, out IPokeGroup? result)
+ private static bool TryGetBundle(byte[] data, [NotNullWhen(true)] out IPokeGroup? result)
{
result = null;
if (RentalTeam8.IsRentalTeam(data))
@@ -138,7 +139,7 @@ public static bool IsFileTooBig(long length)
/// Binary data
/// Output result
/// True if file object reference is valid, false if none found.
- public static bool TryGetSAV(byte[] data, out SaveFile? sav)
+ public static bool TryGetSAV(byte[] data, [NotNullWhen(true)] out SaveFile? sav)
{
sav = SaveUtil.GetVariantSAV(data);
return sav != null;
@@ -150,7 +151,7 @@ public static bool TryGetSAV(byte[] data, out SaveFile? sav)
/// Binary data
/// Output result
/// True if file object reference is valid, false if none found.
- public static bool TryGetMemoryCard(byte[] data, out SAV3GCMemoryCard? memcard)
+ public static bool TryGetMemoryCard(byte[] data, [NotNullWhen(true)] out SAV3GCMemoryCard? memcard)
{
if (!SAV3GCMemoryCard.IsMemoryCardSize(data))
{
@@ -169,7 +170,7 @@ public static bool TryGetMemoryCard(byte[] data, out SAV3GCMemoryCard? memcard)
/// Format hint
/// Reference savefile used for PC Binary compatibility checks.
/// True if file object reference is valid, false if none found.
- public static bool TryGetPKM(byte[] data, out PKM? pk, string ext, ITrainerInfo? sav = null)
+ public static bool TryGetPKM(byte[] data, [NotNullWhen(true)] out PKM? pk, string ext, ITrainerInfo? sav = null)
{
if (ext == ".pgt") // size collision with pk6
{
@@ -211,7 +212,7 @@ public static bool TryGetPCBoxBin(byte[] data, out IEnumerable pkms, Sav
/// Binary data
/// Output result
/// True if file object reference is valid, false if none found.
- public static bool TryGetBattleVideo(byte[] data, out BattleVideo? bv)
+ public static bool TryGetBattleVideo(byte[] data, [NotNullWhen(true)] out BattleVideo? bv)
{
bv = BattleVideo.GetVariantBattleVideo(data);
return bv != null;
@@ -224,7 +225,7 @@ public static bool TryGetBattleVideo(byte[] data, out BattleVideo? bv)
/// Output result
/// Format hint
/// True if file object reference is valid, false if none found.
- public static bool TryGetMysteryGift(byte[] data, out MysteryGift? mg, string ext)
+ public static bool TryGetMysteryGift(byte[] data, [NotNullWhen(true)] out MysteryGift? mg, string ext)
{
mg = MysteryGift.GetMysteryGift(data, ext);
return mg != null;
@@ -256,7 +257,7 @@ public static string GetPKMTempFileName(PKM pk, bool encrypt)
if (!fi.Exists)
return null;
if (fi.Length == GP1.SIZE && TryGetGP1(File.ReadAllBytes(file), out var gp1))
- return gp1?.ConvertToPB7(sav);
+ return gp1.ConvertToPB7(sav);
if (!PKX.IsPKM(fi.Length) && !MysteryGift.IsMysteryGift(fi.Length))
return null;
var data = File.ReadAllBytes(file);
diff --git a/PKHeX.Core/Util/FrameworkUtil.cs b/PKHeX.Core/Util/FrameworkUtil.cs
index f6069cf6d..f255af5f4 100644
--- a/PKHeX.Core/Util/FrameworkUtil.cs
+++ b/PKHeX.Core/Util/FrameworkUtil.cs
@@ -12,10 +12,25 @@ namespace System.Runtime.CompilerServices
/// This class should not be used by developers in source code.
///
[ExcludeFromCodeCoverage, DebuggerNonUserCode]
-#endif
internal static class IsExternalInit
{
}
}
+namespace System.Diagnostics.CodeAnalysis
+{
+ [AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
+ internal sealed class NotNullWhenAttribute : Attribute
+ {
+ /// Initializes the attribute with the specified return value condition.
+ ///
+ /// The return value condition. If the method returns this value, the associated parameter will not be null.
+ ///
+ public NotNullWhenAttribute(bool returnValue) => ReturnValue = returnValue;
+
+ /// Gets the return value condition.
+ public bool ReturnValue { get; }
+ }
+}
#pragma warning restore
+#endif
diff --git a/PKHeX.Core/Util/ReflectUtil.cs b/PKHeX.Core/Util/ReflectUtil.cs
index c0d916050..68bfcaa95 100644
--- a/PKHeX.Core/Util/ReflectUtil.cs
+++ b/PKHeX.Core/Util/ReflectUtil.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Linq;
using System.Reflection;
@@ -120,7 +121,7 @@ public static IEnumerable GetAllTypeInfo(this TypeInfo? typeInfo)
/// Name of the property.
/// Reference to the property info for the object, if it exists.
/// True if has property, and false if does not have property. is null when returning false.
- public static bool HasProperty(object obj, string name, out PropertyInfo? pi) => (pi = GetPropertyInfo(obj.GetType().GetTypeInfo(), name)) != null;
+ public static bool HasProperty(object obj, string name, [NotNullWhen(true)] out PropertyInfo? pi) => (pi = GetPropertyInfo(obj.GetType().GetTypeInfo(), name)) != null;
public static PropertyInfo? GetPropertyInfo(this TypeInfo typeInfo, string name)
{
diff --git a/PKHeX.WinForms/MainWindow/Main.cs b/PKHeX.WinForms/MainWindow/Main.cs
index a893e9060..071a52825 100644
--- a/PKHeX.WinForms/MainWindow/Main.cs
+++ b/PKHeX.WinForms/MainWindow/Main.cs
@@ -971,12 +971,12 @@ private void ImportQRToTabs(string url)
return;
var sav = C_SAV.SAV;
- if (FileUtil.TryGetPKM(input, out var pk, sav.Generation.ToString(), sav) && pk != null)
+ if (FileUtil.TryGetPKM(input, out var pk, sav.Generation.ToString(), sav))
{
OpenPKM(pk);
return;
}
- if (FileUtil.TryGetMysteryGift(input, out var mg, url) && mg != null)
+ if (FileUtil.TryGetMysteryGift(input, out var mg, url))
{
OpenMysteryGift(mg, url);
return;