mirror of
https://github.com/kwsch/PKHeX.git
synced 2026-07-31 03:56:08 -05:00
Add some code analysis for try-return with nullable out
This commit is contained in:
parent
bfd948ee2b
commit
680e8b711d
|
|
@ -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()
|
|||
/// <param name="name">Property Name to check</param>
|
||||
/// <param name="pi">Property Info retrieved (if any).</param>
|
||||
/// <returns>True if has property, false if does not.</returns>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to fetch the <see cref="PKM"/> property from the cache of available properties.
|
||||
/// </summary>
|
||||
/// <param name="type">Type to check</param>
|
||||
/// <param name="name">Property Name to check</param>
|
||||
/// <param name="pi">Property Info retrieved (if any).</param>
|
||||
/// <returns>True if has property, false if does not.</returns>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of <see cref="PKM"/> types that implement the requested <see cref="property"/>.
|
||||
/// </summary>
|
||||
public static IEnumerable<string> 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}";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of the <see cref="PKM"/> property using the saved cache of properties.
|
||||
/// </summary>
|
||||
|
|
@ -160,8 +195,6 @@ public static bool IsFilterMatch(IEnumerable<StringInstruction> filters, object
|
|||
return false;
|
||||
try
|
||||
{
|
||||
if (pi == null)
|
||||
continue;
|
||||
if (pi.IsValueEqual(obj, cmd.PropertyValue) == cmd.Evaluator)
|
||||
continue;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
|||
/// <returns>Indication if Not Transferable</returns>
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
|||
/// <param name="data">Binary data</param>
|
||||
/// <param name="sav">Output result</param>
|
||||
/// <returns>True if file object reference is valid, false if none found.</returns>
|
||||
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)
|
|||
/// <param name="data">Binary data</param>
|
||||
/// <param name="memcard">Output result</param>
|
||||
/// <returns>True if file object reference is valid, false if none found.</returns>
|
||||
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)
|
|||
/// <param name="ext">Format hint</param>
|
||||
/// <param name="sav">Reference savefile used for PC Binary compatibility checks.</param>
|
||||
/// <returns>True if file object reference is valid, false if none found.</returns>
|
||||
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<byte[]> pkms, Sav
|
|||
/// <param name="data">Binary data</param>
|
||||
/// <param name="bv">Output result</param>
|
||||
/// <returns>True if file object reference is valid, false if none found.</returns>
|
||||
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)
|
|||
/// <param name="mg">Output result</param>
|
||||
/// <param name="ext">Format hint</param>
|
||||
/// <returns>True if file object reference is valid, false if none found.</returns>
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -12,10 +12,25 @@ namespace System.Runtime.CompilerServices
|
|||
/// This class should not be used by developers in source code.
|
||||
/// </summary>
|
||||
[ExcludeFromCodeCoverage, DebuggerNonUserCode]
|
||||
#endif
|
||||
internal static class IsExternalInit
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
namespace System.Diagnostics.CodeAnalysis
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
|
||||
internal sealed class NotNullWhenAttribute : Attribute
|
||||
{
|
||||
/// <summary>Initializes the attribute with the specified return value condition.</summary>
|
||||
/// <param name="returnValue">
|
||||
/// The return value condition. If the method returns this value, the associated parameter will not be null.
|
||||
/// </param>
|
||||
public NotNullWhenAttribute(bool returnValue) => ReturnValue = returnValue;
|
||||
|
||||
/// <summary>Gets the return value condition.</summary>
|
||||
public bool ReturnValue { get; }
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -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<TypeInfo> GetAllTypeInfo(this TypeInfo? typeInfo)
|
|||
/// <param name="name">Name of the property.</param>
|
||||
/// <param name="pi">Reference to the property info for the object, if it exists.</param>
|
||||
/// <returns>True if has property, and false if does not have property. <see cref="pi"/> is null when returning false.</returns>
|
||||
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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user