From d55229ee93417355368c6c87758be4c82eafbf23 Mon Sep 17 00:00:00 2001 From: Ivan Migalev Date: Mon, 30 Dec 2024 19:31:22 +0100 Subject: [PATCH] (#41) ImportLogic: do not skip static interface methods --- src/Refasmer/Importer/ImportLogic.cs | 33 ++++++++++++++----- tests/Refasmer.Tests/IntegrationTestBase.cs | 6 +++- tests/Refasmer.Tests/IntegrationTests.cs | 11 +++++++ ...ests.InterfaceImplementations.verified.txt | 14 ++++++++ .../InterfaceImplementations.cs | 19 +++++++++++ .../RefasmerTestAssembly.csproj | 2 +- 6 files changed, 75 insertions(+), 10 deletions(-) create mode 100644 tests/Refasmer.Tests/data/IntegrationTests.InterfaceImplementations.verified.txt create mode 100644 tests/RefasmerTestAssembly/InterfaceImplementations.cs diff --git a/src/Refasmer/Importer/ImportLogic.cs b/src/Refasmer/Importer/ImportLogic.cs index 888074f..52fc080 100644 --- a/src/Refasmer/Importer/ImportLogic.cs +++ b/src/Refasmer/Importer/ImportLogic.cs @@ -87,7 +87,7 @@ private TypeDefinitionHandle ImportTypeDefinitionSkeleton(TypeDefinitionHandle s if (!forcePreservePrivateFields) PostProcessSkippedValueTypeFields(skippedInstanceFields!, importedInstanceFields!); - var implementations = GetAllowedInterfaceMethodImplementations(src); + var implementations = GetCurrentAssemblyInterfaceMethodImplementations(src); foreach (var srcMethodHandle in src.GetMethods()) { @@ -402,12 +402,29 @@ public bool IsReferenceAssembly() => .Select(_reader.GetFullname) .Any(name => name == FullNames.ReferenceAssembly); - private ImmutableHashSet GetAllowedInterfaceMethodImplementations(TypeDefinition type) => - type.GetMethodImplementations() - .Select(_reader.GetMethodImplementation) - .Where(mi => AllowImportType(_reader.GetMethodClass(mi.MethodDeclaration))) - .Select(mi => (MethodDefinitionHandle)mi.MethodBody) - .ToImmutableHashSet(); + private ImmutableHashSet GetCurrentAssemblyInterfaceMethodImplementations( + TypeDefinition type) + { + return GetImplementations().ToImmutableHashSet(); + + IEnumerable GetImplementations() + { + var implementations = type.GetMethodImplementations() + .Select(_reader.GetMethodImplementation); + foreach (var mi in implementations) + { + if (!AllowImportType(_reader.GetMethodClass(mi.MethodDeclaration))) + continue; + + var bodyHandle = (MethodDefinitionHandle)mi.MethodBody; + var method = _reader.GetMethodDefinition(bodyHandle); + var isStatic = (method.Attributes & MethodAttributes.Static) != 0; + if (isStatic) continue; + + yield return bodyHandle; + } + } + } private bool AllowImportMethod( IImmutableSet implementations, @@ -655,7 +672,7 @@ private IEnumerable CalculateInternalTypesToPreserve( AcceptFieldSignature(field, collector); } - var methodImplementations = GetAllowedInterfaceMethodImplementations(type); + var methodImplementations = GetCurrentAssemblyInterfaceMethodImplementations(type); foreach (var methodHandle in type.GetMethods()) { var method = _reader.GetMethodDefinition(methodHandle); diff --git a/tests/Refasmer.Tests/IntegrationTestBase.cs b/tests/Refasmer.Tests/IntegrationTestBase.cs index 5de5758..91a4b7e 100644 --- a/tests/Refasmer.Tests/IntegrationTestBase.cs +++ b/tests/Refasmer.Tests/IntegrationTestBase.cs @@ -7,6 +7,8 @@ namespace JetBrains.Refasmer.Tests; public abstract class IntegrationTestBase { + private const string TestAssemblyTargetFramework = "net7.0"; + protected static async Task BuildTestAssembly() { var root = FindSourceRoot(); @@ -19,7 +21,9 @@ protected static async Task BuildTestAssembly() Is.EqualTo(0), $"Failed to build test assembly, exit code {result.ExitCode}. StdOut:\n{result.StandardOutput}\nStdErr: {result.StandardError}"); - return Path.Combine(root, "tests/RefasmerTestAssembly/bin/Release/net6.0/RefasmerTestAssembly.dll"); + return Path.Combine( + root, + $"tests/RefasmerTestAssembly/bin/Release/{TestAssemblyTargetFramework}/RefasmerTestAssembly.dll"); } protected static async Task BuildTestAssemblyWithInternalTypeInPublicApi() diff --git a/tests/Refasmer.Tests/IntegrationTests.cs b/tests/Refasmer.Tests/IntegrationTests.cs index cea0d85..f5d6a38 100644 --- a/tests/Refasmer.Tests/IntegrationTests.cs +++ b/tests/Refasmer.Tests/IntegrationTests.cs @@ -66,4 +66,15 @@ await VerifyTypeContents( assertTypeExists: false, parameters: [mainClassName]); } + + [Test] + public async Task InterfaceImplementations() + { + var assemblyPath = await BuildTestAssemblyWithInternalTypeInPublicApi(); + var resultAssembly = RefasmTestAssembly(assemblyPath, omitNonApiMembers: true); + + await VerifyTypeContents( + resultAssembly, + ["RefasmerTestAssembly.InterfaceImplementations", "RefasmerTestAssembly.IWithStaticMethods`1"]); + } } diff --git a/tests/Refasmer.Tests/data/IntegrationTests.InterfaceImplementations.verified.txt b/tests/Refasmer.Tests/data/IntegrationTests.InterfaceImplementations.verified.txt new file mode 100644 index 0000000..4b6aea2 --- /dev/null +++ b/tests/Refasmer.Tests/data/IntegrationTests.InterfaceImplementations.verified.txt @@ -0,0 +1,14 @@ +public class: RefasmerTestAssembly.InterfaceImplementations + - interface impl: RefasmerTestAssembly.IWithStaticMethods`1 +methods: +- Equals(System.Object obj): System.Boolean: +- GetHashCode(): System.Int32: +- op_Equality(RefasmerTestAssembly.InterfaceImplementations a, RefasmerTestAssembly.InterfaceImplementations b): System.Boolean: +- op_Inequality(RefasmerTestAssembly.InterfaceImplementations a, RefasmerTestAssembly.InterfaceImplementations b): System.Boolean: +- .ctor(): System.Void: +public interface: RefasmerTestAssembly.IWithStaticMethods`1 +methods: +- op_Equality(TSelf a, TSelf b): System.Boolean: + - +- op_Inequality(TSelf a, TSelf b): System.Boolean: + - diff --git a/tests/RefasmerTestAssembly/InterfaceImplementations.cs b/tests/RefasmerTestAssembly/InterfaceImplementations.cs new file mode 100644 index 0000000..8ebf116 --- /dev/null +++ b/tests/RefasmerTestAssembly/InterfaceImplementations.cs @@ -0,0 +1,19 @@ +using System; + +namespace RefasmerTestAssembly; + +public interface IWithStaticMethods where TSelf : IWithStaticMethods +{ + static abstract bool operator ==(TSelf a, TSelf b); + static abstract bool operator !=(TSelf a, TSelf b); +} +public class InterfaceImplementations : IWithStaticMethods +{ + public override bool Equals(object? obj) => throw new NotSupportedException(); + + public override int GetHashCode() => throw new NotSupportedException(); + + public static bool operator ==(InterfaceImplementations a, InterfaceImplementations b) => throw new NotSupportedException(); + + public static bool operator !=(InterfaceImplementations a, InterfaceImplementations b) => throw new NotSupportedException(); +} diff --git a/tests/RefasmerTestAssembly/RefasmerTestAssembly.csproj b/tests/RefasmerTestAssembly/RefasmerTestAssembly.csproj index 3dae7b0..94178a5 100644 --- a/tests/RefasmerTestAssembly/RefasmerTestAssembly.csproj +++ b/tests/RefasmerTestAssembly/RefasmerTestAssembly.csproj @@ -1,7 +1,7 @@ - net6.0 + net7.0 Latest true true