Skip to content

Commit d4edb5c

Browse files
authored
#470 Improved handling of sibling interfaces (#471)
* #470 Improved handling of sibling interfaces * Merged redundant linq calls
1 parent 8d0a650 commit d4edb5c

15 files changed

Lines changed: 190 additions & 18 deletions

File tree

Confuser.Renamer/Analyzers/VTableAnalyzer.cs

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,17 @@ public static void Analyze(INameService service, ICollection<ModuleDefMD> module
4646
// case here.
4747
if (!TypeEqualityComparer.Instance.Equals(slot.MethodDef.DeclaringType, type)) {
4848
SetupOverwriteReferences(service, modules, slot, type);
49-
//CreateOverrideReference(service, slot.MethodDef, slot.Overrides.MethodDef);
49+
50+
// If required, create the sibling references, so the names of the interfaces line up correctly.
51+
var existingReferences = service.GetReferences(slot.MethodDef);
52+
var overrideDef = existingReferences
53+
.OfType<MemberOverrideReference>()
54+
.FirstOrDefault(r => !MethodEqualityComparer.CompareDeclaringTypes.Equals(r.BaseMemberDef as MethodDef, slot.Overrides.MethodDef));
55+
56+
if (!(overrideDef is null)) {
57+
var baseMemberDef = overrideDef.BaseMemberDef;
58+
CreateSiblingReference(slot.Overrides.MethodDef, ref baseMemberDef, service);
59+
}
5060
}
5161

5262
// For the case when method in base type implements an interface method for a derived type
@@ -67,9 +77,6 @@ public static void Analyze(INameService service, ICollection<ModuleDefMD> module
6777
if (!method.IsVirtual)
6878
return;
6979

70-
var vTbl = service.GetVTables()[method.DeclaringType];
71-
var slots = vTbl.FindSlots(method).ToArray();
72-
7380
IMemberDef discoveredBaseMemberDef = null;
7481
MethodDef discoveredBaseMethodDef = null;
7582

@@ -118,6 +125,9 @@ public static void Analyze(INameService service, ICollection<ModuleDefMD> module
118125
}
119126

120127
if (!method.IsAbstract) {
128+
var vTbl = service.GetVTables()[method.DeclaringType];
129+
var slots = vTbl.FindSlots(method).ToArray();
130+
121131
foreach (var slot in slots) {
122132
if (slot.Overrides == null)
123133
continue;
@@ -132,9 +142,9 @@ public static void Analyze(INameService service, ICollection<ModuleDefMD> module
132142
}
133143
}
134144

135-
static void CreateSiblingReference<T>(T basePropDef, ref T discoveredBaseMemberDef, INameService service) where T : class, IMemberDef {
145+
static void CreateSiblingReference<T>(T baseMemberDef, ref T discoveredBaseMemberDef, INameService service) where T : class, IMemberDef {
136146
if (discoveredBaseMemberDef is null)
137-
discoveredBaseMemberDef = basePropDef;
147+
discoveredBaseMemberDef = baseMemberDef;
138148
else {
139149
var references = service.GetReferences(discoveredBaseMemberDef)
140150
.OfType<MemberSiblingReference>()
@@ -148,12 +158,12 @@ static void CreateSiblingReference<T>(T basePropDef, ref T discoveredBaseMemberD
148158
}
149159

150160
// Check if the discovered base type is the current type. If so, nothing needs to be done.
151-
if (ReferenceEquals(basePropDef, discoveredBaseMemberDef)) return;
161+
if (ReferenceEquals(baseMemberDef, discoveredBaseMemberDef)) return;
152162

153-
var reference = new MemberSiblingReference(basePropDef, discoveredBaseMemberDef);
154-
service.AddReference(basePropDef, reference);
163+
var reference = new MemberSiblingReference(baseMemberDef, discoveredBaseMemberDef);
164+
service.AddReference(baseMemberDef, reference);
155165
service.AddReference(discoveredBaseMemberDef, reference);
156-
UpdateOldestSiblingReference(discoveredBaseMemberDef, basePropDef, service);
166+
UpdateOldestSiblingReference(discoveredBaseMemberDef, baseMemberDef, service);
157167
}
158168
}
159169

Confuser.Renamer/References/MemberOverrideReference.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@
66

77
namespace Confuser.Renamer.References {
88
public sealed class MemberOverrideReference : INameReference<IDnlibDef> {
9-
readonly IMemberDef thisMemberDef;
9+
internal IMemberDef ThisMemberDef { get; }
1010
internal IMemberDef BaseMemberDef { get; }
1111

12-
public bool ShouldCancelRename => thisMemberDef.Module != BaseMemberDef.Module;
12+
public bool ShouldCancelRename => ThisMemberDef.Module != BaseMemberDef.Module;
1313

1414
public MemberOverrideReference(IMemberDef thisMemberDef, IMemberDef baseMemberDef) {
15-
this.thisMemberDef = thisMemberDef ?? throw new ArgumentNullException(nameof(thisMemberDef));
15+
ThisMemberDef = thisMemberDef ?? throw new ArgumentNullException(nameof(thisMemberDef));
1616
BaseMemberDef = baseMemberDef ?? throw new ArgumentNullException(nameof(baseMemberDef));
1717
Debug.Assert(thisMemberDef != baseMemberDef);
1818
}
@@ -24,8 +24,8 @@ public bool DelayRenaming(INameService service, IDnlibDef currentDef) =>
2424
&& !service.IsRenamed(BaseMemberDef);
2525

2626
public bool UpdateNameReference(ConfuserContext context, INameService service) {
27-
if (UTF8String.Equals(thisMemberDef.Name, BaseMemberDef.Name)) return false;
28-
thisMemberDef.Name = BaseMemberDef.Name;
27+
if (UTF8String.Equals(ThisMemberDef.Name, BaseMemberDef.Name)) return false;
28+
ThisMemberDef.Name = BaseMemberDef.Name;
2929
return true;
3030
}
3131

@@ -34,7 +34,7 @@ public bool UpdateNameReference(ConfuserContext context, INameService service) {
3434
public string ToString(INameService nameService) {
3535
var builder = new StringBuilder();
3636
builder.Append("Member Override Reference").Append("(");
37-
builder.Append("This ").AppendReferencedDef(thisMemberDef, nameService);
37+
builder.Append("This ").AppendReferencedDef(ThisMemberDef, nameService);
3838
builder.Append("; ");
3939
builder.Append("Base ").AppendReferencedDef(BaseMemberDef, nameService);
4040
builder.Append(")");

Confuser2.sln

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,9 +143,13 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BlockingReferencesHelper",
143143
EndProject
144144
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BlockingReferences.Test", "Tests\BlockingReferences.Test\BlockingReferences.Test.csproj", "{4FB03AD0-96FF-4730-801A-4F997795D920}"
145145
EndProject
146-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "421_NewtonsoftJsonSerialization", "Tests\421_NewtonsoftJsonSerialization\421_NewtonsoftJsonSerialization.csproj", "{4EF73752-78B0-4E0D-A33B-B6637B6C2177}"
146+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "421_NewtonsoftJsonSerialization", "Tests\421_NewtonsoftJsonSerialization\421_NewtonsoftJsonSerialization.csproj", "{4EF73752-78B0-4E0D-A33B-B6637B6C2177}"
147147
EndProject
148-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "421_NewtonsoftJsonSerialization.Test", "Tests\421_NewtonsoftJsonSerialization.Test\421_NewtonsoftJsonSerialization.Test.csproj", "{B1CB9A30-FEA6-4467-BEC5-4803CCE9BF78}"
148+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "421_NewtonsoftJsonSerialization.Test", "Tests\421_NewtonsoftJsonSerialization.Test\421_NewtonsoftJsonSerialization.Test.csproj", "{B1CB9A30-FEA6-4467-BEC5-4803CCE9BF78}"
149+
EndProject
150+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "470_ImplementationInBaseClass", "Tests\470_ImplementationInBaseClass\470_ImplementationInBaseClass.csproj", "{5D10ED0A-6C52-49FE-90F5-CFAAECA8FABE}"
151+
EndProject
152+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "470_ImplementationInBaseClass.Test", "Tests\470_ImplementationInBaseClass.Test\470_ImplementationInBaseClass.Test.csproj", "{F7581FB4-FAF5-4CD0-888A-B588F5BC69CD}"
149153
EndProject
150154
Global
151155
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -937,6 +941,30 @@ Global
937941
{B1CB9A30-FEA6-4467-BEC5-4803CCE9BF78}.Release|x64.Build.0 = Release|Any CPU
938942
{B1CB9A30-FEA6-4467-BEC5-4803CCE9BF78}.Release|x86.ActiveCfg = Release|Any CPU
939943
{B1CB9A30-FEA6-4467-BEC5-4803CCE9BF78}.Release|x86.Build.0 = Release|Any CPU
944+
{5D10ED0A-6C52-49FE-90F5-CFAAECA8FABE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
945+
{5D10ED0A-6C52-49FE-90F5-CFAAECA8FABE}.Debug|Any CPU.Build.0 = Debug|Any CPU
946+
{5D10ED0A-6C52-49FE-90F5-CFAAECA8FABE}.Debug|x64.ActiveCfg = Debug|Any CPU
947+
{5D10ED0A-6C52-49FE-90F5-CFAAECA8FABE}.Debug|x64.Build.0 = Debug|Any CPU
948+
{5D10ED0A-6C52-49FE-90F5-CFAAECA8FABE}.Debug|x86.ActiveCfg = Debug|Any CPU
949+
{5D10ED0A-6C52-49FE-90F5-CFAAECA8FABE}.Debug|x86.Build.0 = Debug|Any CPU
950+
{5D10ED0A-6C52-49FE-90F5-CFAAECA8FABE}.Release|Any CPU.ActiveCfg = Release|Any CPU
951+
{5D10ED0A-6C52-49FE-90F5-CFAAECA8FABE}.Release|Any CPU.Build.0 = Release|Any CPU
952+
{5D10ED0A-6C52-49FE-90F5-CFAAECA8FABE}.Release|x64.ActiveCfg = Release|Any CPU
953+
{5D10ED0A-6C52-49FE-90F5-CFAAECA8FABE}.Release|x64.Build.0 = Release|Any CPU
954+
{5D10ED0A-6C52-49FE-90F5-CFAAECA8FABE}.Release|x86.ActiveCfg = Release|Any CPU
955+
{5D10ED0A-6C52-49FE-90F5-CFAAECA8FABE}.Release|x86.Build.0 = Release|Any CPU
956+
{F7581FB4-FAF5-4CD0-888A-B588F5BC69CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
957+
{F7581FB4-FAF5-4CD0-888A-B588F5BC69CD}.Debug|Any CPU.Build.0 = Debug|Any CPU
958+
{F7581FB4-FAF5-4CD0-888A-B588F5BC69CD}.Debug|x64.ActiveCfg = Debug|Any CPU
959+
{F7581FB4-FAF5-4CD0-888A-B588F5BC69CD}.Debug|x64.Build.0 = Debug|Any CPU
960+
{F7581FB4-FAF5-4CD0-888A-B588F5BC69CD}.Debug|x86.ActiveCfg = Debug|Any CPU
961+
{F7581FB4-FAF5-4CD0-888A-B588F5BC69CD}.Debug|x86.Build.0 = Debug|Any CPU
962+
{F7581FB4-FAF5-4CD0-888A-B588F5BC69CD}.Release|Any CPU.ActiveCfg = Release|Any CPU
963+
{F7581FB4-FAF5-4CD0-888A-B588F5BC69CD}.Release|Any CPU.Build.0 = Release|Any CPU
964+
{F7581FB4-FAF5-4CD0-888A-B588F5BC69CD}.Release|x64.ActiveCfg = Release|Any CPU
965+
{F7581FB4-FAF5-4CD0-888A-B588F5BC69CD}.Release|x64.Build.0 = Release|Any CPU
966+
{F7581FB4-FAF5-4CD0-888A-B588F5BC69CD}.Release|x86.ActiveCfg = Release|Any CPU
967+
{F7581FB4-FAF5-4CD0-888A-B588F5BC69CD}.Release|x86.Build.0 = Release|Any CPU
940968
EndGlobalSection
941969
GlobalSection(SolutionProperties) = preSolution
942970
HideSolutionNode = FALSE
@@ -999,6 +1027,8 @@ Global
9991027
{4FB03AD0-96FF-4730-801A-4F997795D920} = {356BDB31-853E-43BB-8F9A-D8AC08F69EBB}
10001028
{4EF73752-78B0-4E0D-A33B-B6637B6C2177} = {356BDB31-853E-43BB-8F9A-D8AC08F69EBB}
10011029
{B1CB9A30-FEA6-4467-BEC5-4803CCE9BF78} = {356BDB31-853E-43BB-8F9A-D8AC08F69EBB}
1030+
{5D10ED0A-6C52-49FE-90F5-CFAAECA8FABE} = {356BDB31-853E-43BB-8F9A-D8AC08F69EBB}
1031+
{F7581FB4-FAF5-4CD0-888A-B588F5BC69CD} = {356BDB31-853E-43BB-8F9A-D8AC08F69EBB}
10021032
EndGlobalSection
10031033
GlobalSection(ExtensibilityGlobals) = postSolution
10041034
SolutionGuid = {0D937D9E-E04B-4A68-B639-D4260473A388}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net461</TargetFramework>
5+
<RootNamespace>ImplementationInBaseClass.Test</RootNamespace>
6+
<IsPackable>false</IsPackable>
7+
</PropertyGroup>
8+
9+
<ItemGroup>
10+
<ProjectReference Include="..\Confuser.UnitTest\Confuser.UnitTest.csproj" />
11+
<ProjectReference Include="..\470_ImplementationInBaseClass\470_ImplementationInBaseClass.csproj" />
12+
</ItemGroup>
13+
14+
</Project>
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
using System.Collections.Generic;
2+
using System.Threading.Tasks;
3+
using Confuser.Core;
4+
using Confuser.Core.Project;
5+
using Confuser.Renamer;
6+
using Confuser.UnitTest;
7+
using Xunit;
8+
using Xunit.Abstractions;
9+
10+
namespace ImplementationInBaseClass.Test
11+
{
12+
public class RenameTest : TestBase
13+
{
14+
public RenameTest(ITestOutputHelper outputHelper) : base(outputHelper) { }
15+
16+
[Theory]
17+
[MemberData(nameof(ResolveNameData))]
18+
[Trait("Category", "Protection")]
19+
[Trait("Protection", "rename")]
20+
[Trait("Issue", "https://github.com/mkaring/ConfuserEx/issues/470")]
21+
public async Task ResolveNameLoop(RenameMode mode, bool flatten) =>
22+
await Run(
23+
new[] {
24+
"470_ImplementationInBaseClass.exe"
25+
},
26+
new[] {
27+
"Called MyMethod",
28+
"Called MyMethod",
29+
"Called MyMethod",
30+
"Called MyMethod"
31+
},
32+
new SettingItem<Protection>("rename") {
33+
{ "mode", mode.ToString() },
34+
{ "renPublic", "true" },
35+
{ "flatten", flatten.ToString() }
36+
},
37+
$"_{mode}_{flatten}"
38+
);
39+
40+
public static IEnumerable<object[]> ResolveNameData() {
41+
foreach (var renameMode in new[] { RenameMode.Unicode, RenameMode.Sequential })
42+
foreach (var flatten in new[] { true, false })
43+
yield return new object[] { renameMode, flatten };
44+
}
45+
}
46+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>net461</TargetFramework>
6+
<RootNamespace>ImplementationInBaseClass</RootNamespace>
7+
<LangVersion>7.3</LangVersion>
8+
</PropertyGroup>
9+
10+
</Project>
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
namespace ImplementationInBaseClass {
2+
public interface IMyInterfaceA {
3+
void MyMethod();
4+
}
5+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
namespace ImplementationInBaseClass {
2+
public interface IMyInterfaceB {
3+
void MyMethod();
4+
}
5+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
namespace ImplementationInBaseClass {
2+
public interface IMyInterfaceC {
3+
void MyMethod();
4+
}
5+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
using System;
2+
3+
namespace ImplementationInBaseClass {
4+
internal abstract class MyBaseClass {
5+
public void MyMethod() => Console.WriteLine("Called " + nameof(MyMethod));
6+
}
7+
}

0 commit comments

Comments
 (0)