Skip to content

Commit 488ade7

Browse files
authored
Merge pull request #243 from Bip901/fix/base-types
Improve the base type analyzer, making it more explicit
2 parents 9cea8d0 + 4e90cb5 commit 488ade7

File tree

2 files changed

+62
-13
lines changed

2 files changed

+62
-13
lines changed
Lines changed: 57 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
namespace BitMono.Core.Analyzing;
1+
using System.Text.RegularExpressions;
2+
3+
namespace BitMono.Core.Analyzing;
24

3-
[SuppressMessage("ReSharper", "InvertIf")]
45
public class CriticalBaseTypesCriticalAnalyzer : ICriticalAnalyzer<TypeDefinition>
56
{
67
private readonly CriticalsSettings _criticalsSettings;
@@ -12,19 +13,68 @@ public CriticalBaseTypesCriticalAnalyzer(IOptions<CriticalsSettings> criticals)
1213

1314
public bool NotCriticalToMakeChanges(TypeDefinition type)
1415
{
15-
if (_criticalsSettings.UseCriticalBaseTypes == false)
16+
if (!_criticalsSettings.UseCriticalBaseTypes)
1617
{
1718
return true;
1819
}
19-
if (type.HasBaseType())
20+
foreach (string ancestorFullName in YieldAncestors(type))
2021
{
21-
var criticalBaseTypes = _criticalsSettings.CriticalBaseTypes!;
22-
var typeBaseTypeName = type.BaseType?.Name?.Value.Split('`')[0] ?? string.Empty;
23-
if (criticalBaseTypes.FirstOrDefault(c => c.StartsWith(typeBaseTypeName)) != null)
22+
if (IsCriticalBaseType(ancestorFullName))
2423
{
2524
return false;
2625
}
2726
}
2827
return true;
2928
}
29+
30+
private bool IsCriticalBaseType(string ancestorFullName)
31+
{
32+
ancestorFullName = StripGenerics(ancestorFullName);
33+
foreach (string criticalBaseType in _criticalsSettings.CriticalBaseTypes)
34+
{
35+
bool matches;
36+
if (criticalBaseType.Contains('*'))
37+
{
38+
string regex = "^" + Regex.Escape(criticalBaseType).Replace(@"\*", ".*") + "$";
39+
matches = Regex.IsMatch(ancestorFullName, regex);
40+
}
41+
else
42+
{
43+
matches = criticalBaseType == ancestorFullName;
44+
}
45+
if (matches)
46+
{
47+
return true;
48+
}
49+
}
50+
return false;
51+
}
52+
53+
private static string StripGenerics(string fullName)
54+
{
55+
int genericDelimeterIndex = fullName.IndexOf('`');
56+
if (genericDelimeterIndex == -1)
57+
{
58+
return fullName;
59+
}
60+
return fullName[..genericDelimeterIndex];
61+
}
62+
63+
/// <summary>
64+
/// Yields the full class names of all ancestors across the inheritence chain of <paramref name="current"/>, including itself.
65+
/// </summary>
66+
private static IEnumerable<string> YieldAncestors(TypeDefinition? current)
67+
{
68+
while (current != null)
69+
{
70+
yield return current.FullName;
71+
ITypeDefOrRef? baseType = current.BaseType;
72+
current = baseType?.Resolve();
73+
if (current == null && baseType != null)
74+
{
75+
//Type is in an unresolved dependency assembly, stop the search but yield the type name
76+
yield return baseType.FullName;
77+
}
78+
}
79+
}
3080
}

src/BitMono.Host/criticals.json

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,16 +70,15 @@
7070
"UseCriticalBaseTypes": true,
7171
"CriticalBaseTypes": [
7272
// RocketMod
73-
"RocketPlugin",
73+
"RocketPlugin*",
7474

7575
// OpenMod
76-
"OpenModUnturnedPlugin",
77-
"OpenModUniversalPlugin",
78-
"Command",
76+
"OpenModUnturnedPlugin*",
77+
"OpenModUniversalPlugin*",
78+
"Command*",
7979

8080
// rust-oxide-umod
81-
"RustPlugin"
82-
81+
"RustPlugin*"
8382
],
8483

8584
// Exclude from obfuscation if the member starts with string

0 commit comments

Comments
 (0)