encapsulate GetComparableTypeID
This commit is contained in:
parent
40fbafdb73
commit
befeafd31d
|
@ -1,6 +1,5 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using Mono.Cecil;
|
||||
using Mono.Cecil.Cil;
|
||||
|
||||
|
@ -16,9 +15,6 @@ namespace StardewModdingAPI.Framework.ModLoading.Finders
|
|||
/// <summary>The assembly names to which to heuristically detect broken references.</summary>
|
||||
private readonly HashSet<string> ValidateReferencesToAssemblies;
|
||||
|
||||
/// <summary>A pattern matching type name substrings to strip for display.</summary>
|
||||
private readonly Regex StripTypeNamePattern = new Regex(@"`\d+(?=<)", RegexOptions.Compiled);
|
||||
|
||||
|
||||
/*********
|
||||
** Accessors
|
||||
|
@ -65,12 +61,9 @@ namespace StardewModdingAPI.Framework.ModLoading.Finders
|
|||
return InstructionHandleResult.None;
|
||||
|
||||
// validate return type
|
||||
string actualReturnTypeID = this.GetComparableTypeID(targetField.FieldType);
|
||||
string expectedReturnTypeID = this.GetComparableTypeID(fieldRef.FieldType);
|
||||
|
||||
if (!RewriteHelper.LooksLikeSameType(expectedReturnTypeID, actualReturnTypeID))
|
||||
if (!RewriteHelper.LooksLikeSameType(fieldRef.FieldType, targetField.FieldType))
|
||||
{
|
||||
this.NounPhrase = $"reference to {fieldRef.DeclaringType.FullName}.{fieldRef.Name} (field returns {this.GetFriendlyTypeName(targetField.FieldType, actualReturnTypeID)}, not {this.GetFriendlyTypeName(fieldRef.FieldType, expectedReturnTypeID)})";
|
||||
this.NounPhrase = $"reference to {fieldRef.DeclaringType.FullName}.{fieldRef.Name} (field returns {this.GetFriendlyTypeName(targetField.FieldType)}, not {this.GetFriendlyTypeName(fieldRef.FieldType)})";
|
||||
return InstructionHandleResult.NotCompatible;
|
||||
}
|
||||
}
|
||||
|
@ -92,10 +85,9 @@ namespace StardewModdingAPI.Framework.ModLoading.Finders
|
|||
return InstructionHandleResult.NotCompatible;
|
||||
}
|
||||
|
||||
string expectedReturnType = this.GetComparableTypeID(methodDef.ReturnType);
|
||||
if (candidateMethods.All(method => !RewriteHelper.LooksLikeSameType(this.GetComparableTypeID(method.ReturnType), expectedReturnType)))
|
||||
if (candidateMethods.All(method => !RewriteHelper.LooksLikeSameType(method.ReturnType, methodDef.ReturnType)))
|
||||
{
|
||||
this.NounPhrase = $"reference to {methodDef.DeclaringType.FullName}.{methodDef.Name} (no such method returns {this.GetFriendlyTypeName(methodDef.ReturnType, expectedReturnType)})";
|
||||
this.NounPhrase = $"reference to {methodDef.DeclaringType.FullName}.{methodDef.Name} (no such method returns {this.GetFriendlyTypeName(methodDef.ReturnType)})";
|
||||
return InstructionHandleResult.NotCompatible;
|
||||
}
|
||||
}
|
||||
|
@ -114,17 +106,9 @@ namespace StardewModdingAPI.Framework.ModLoading.Finders
|
|||
return type != null && this.ValidateReferencesToAssemblies.Contains(type.Scope.Name);
|
||||
}
|
||||
|
||||
/// <summary>Get a unique string representation of a type.</summary>
|
||||
/// <param name="type">The type reference.</param>
|
||||
private string GetComparableTypeID(TypeReference type)
|
||||
{
|
||||
return this.StripTypeNamePattern.Replace(type.FullName, "");
|
||||
}
|
||||
|
||||
/// <summary>Get a shorter type name for display.</summary>
|
||||
/// <param name="type">The type reference.</param>
|
||||
/// <param name="typeID">The comparable type ID from <see cref="GetComparableTypeID"/>.</param>
|
||||
private string GetFriendlyTypeName(TypeReference type, string typeID)
|
||||
private string GetFriendlyTypeName(TypeReference type)
|
||||
{
|
||||
// most common built-in types
|
||||
switch (type.FullName)
|
||||
|
@ -141,10 +125,10 @@ namespace StardewModdingAPI.Framework.ModLoading.Finders
|
|||
foreach (string @namespace in new[] { "Microsoft.Xna.Framework", "Netcode", "System", "System.Collections.Generic" })
|
||||
{
|
||||
if (type.Namespace == @namespace)
|
||||
return typeID.Substring(@namespace.Length + 1);
|
||||
return type.Name;
|
||||
}
|
||||
|
||||
return typeID;
|
||||
return type.FullName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text.RegularExpressions;
|
||||
using Mono.Cecil;
|
||||
using Mono.Cecil.Cil;
|
||||
|
||||
|
@ -10,6 +11,13 @@ namespace StardewModdingAPI.Framework.ModLoading
|
|||
/// <summary>Provides helper methods for field rewriters.</summary>
|
||||
internal static class RewriteHelper
|
||||
{
|
||||
/*********
|
||||
** Properties
|
||||
*********/
|
||||
/// <summary>A pattern matching type name substrings to strip for display.</summary>
|
||||
private static readonly Regex StripTypeNamePattern = new Regex(@"`\d+(?=<)", RegexOptions.Compiled);
|
||||
|
||||
|
||||
/*********
|
||||
** Public methods
|
||||
*********/
|
||||
|
@ -109,29 +117,39 @@ namespace StardewModdingAPI.Framework.ModLoading
|
|||
}
|
||||
|
||||
/// <summary>Determine whether two type IDs look like the same type, accounting for placeholder values such as !0.</summary>
|
||||
/// <param name="typeA">The type ID to compare.</param>
|
||||
/// <param name="typeB">The other type ID to compare.</param>
|
||||
/// <param name="a">The type ID to compare.</param>
|
||||
/// <param name="b">The other type ID to compare.</param>
|
||||
/// <returns>true if the type IDs look like the same type, false if not.</returns>
|
||||
public static bool LooksLikeSameType(string typeA, string typeB)
|
||||
public static bool LooksLikeSameType(TypeReference a, TypeReference b)
|
||||
{
|
||||
string typeA = RewriteHelper.GetComparableTypeID(a);
|
||||
string typeB = RewriteHelper.GetComparableTypeID(b);
|
||||
|
||||
string placeholderType = "", actualType = "";
|
||||
|
||||
if (RewriteHelper.HasPlaceholder(typeA))
|
||||
{
|
||||
placeholderType = typeA;
|
||||
actualType = typeB;
|
||||
} else if (RewriteHelper.HasPlaceholder(typeB))
|
||||
}
|
||||
else if (RewriteHelper.HasPlaceholder(typeB))
|
||||
{
|
||||
placeholderType = typeB;
|
||||
actualType = typeA;
|
||||
} else
|
||||
{
|
||||
return typeA == typeB;
|
||||
}
|
||||
else
|
||||
return typeA == typeB;
|
||||
|
||||
return RewriteHelper.PlaceholderTypeValidates(placeholderType, actualType);
|
||||
}
|
||||
|
||||
/// <summary>Get a unique string representation of a type.</summary>
|
||||
/// <param name="type">The type reference.</param>
|
||||
private static string GetComparableTypeID(TypeReference type)
|
||||
{
|
||||
return RewriteHelper.StripTypeNamePattern.Replace(type.FullName, "");
|
||||
}
|
||||
|
||||
protected class SymbolLocation
|
||||
{
|
||||
public string symbol;
|
||||
|
@ -144,7 +162,7 @@ namespace StardewModdingAPI.Framework.ModLoading
|
|||
}
|
||||
}
|
||||
|
||||
private static List<char> symbolBoundaries = new List<char>{'<', '>', ','};
|
||||
private static List<char> symbolBoundaries = new List<char> { '<', '>', ',' };
|
||||
|
||||
/// <summary> Traverses and parses out symbols from a type which does not contain placeholder values.</summary>
|
||||
/// <param name="type">The type to traverse.</param>
|
||||
|
@ -160,7 +178,8 @@ namespace StardewModdingAPI.Framework.ModLoading
|
|||
{
|
||||
typeSymbols.Add(new SymbolLocation(symbol, depth));
|
||||
symbol = "";
|
||||
switch (c) {
|
||||
switch (c)
|
||||
{
|
||||
case '<':
|
||||
depth++;
|
||||
break;
|
||||
|
@ -186,7 +205,8 @@ namespace StardewModdingAPI.Framework.ModLoading
|
|||
if (symbolA.depth != symbolB.depth)
|
||||
return false;
|
||||
|
||||
if (!RewriteHelper.IsPlaceholder(symbolA.symbol)) {
|
||||
if (!RewriteHelper.IsPlaceholder(symbolA.symbol))
|
||||
{
|
||||
return symbolA.symbol == symbolB.symbol;
|
||||
}
|
||||
|
||||
|
@ -245,7 +265,8 @@ namespace StardewModdingAPI.Framework.ModLoading
|
|||
/// <param name="placeholderType">The type with placeholders in it.</param>
|
||||
/// <param name="actualType">The type without placeholders.</param>
|
||||
/// <returns>true if the placeholder type can resolve to the actual type, false if not.</returns>
|
||||
private static bool PlaceholderTypeValidates(string placeholderType, string actualType) {
|
||||
private static bool PlaceholderTypeValidates(string placeholderType, string actualType)
|
||||
{
|
||||
List<SymbolLocation> typeSymbols = new List<SymbolLocation>();
|
||||
|
||||
RewriteHelper.TraverseActualType(actualType, typeSymbols);
|
||||
|
|
Loading…
Reference in New Issue