From 868a6065d52a0a706a37944965550edca422d41e Mon Sep 17 00:00:00 2001 From: Ivan Migalev Date: Sat, 28 Dec 2024 19:25:18 +0100 Subject: [PATCH 1/7] Release: prepare v2.0.1-pre01 --- CHANGELOG.md | 6 +++++- src/Directory.Build.props | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 334daa4..831daf1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## [Unreleased] +### Fixed +- [#38: Internal types in public API break `omit-non-api-members=true`](https://github.com/JetBrains/Refasmer/issues/38). + ## [2.0.0] - 2024-11-20 ### Changed - **(Breaking change!)** A new mandatory parameter `--omit-non-api-types` (pass either `true` or `false`). @@ -185,4 +189,4 @@ Release the initial version in form of a .NET executable and a NuGet package. [1.0.32]: https://github.com/JetBrains/Refasmer/compare/1.0.31...1.0.32 [1.0.33]: https://github.com/JetBrains/Refasmer/compare/1.0.32...1.0.33 [2.0.0]: https://github.com/JetBrains/Refasmer/compare/1.0.33...v2.0.0 -[Unreleased]: https://github.com/JetBrains/Refasmer/compare/1.0.33...HEAD +[Unreleased]: https://github.com/JetBrains/Refasmer/compare/v2.0.0...HEAD diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 327977a..410ca59 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -1,6 +1,6 @@  - 2.0 + 2.0.1-pre01 Copyright © JetBrains 2024 Apache-2.0 From da5cc5ccea1afeeafd3ba85d252d7f1b2704684d Mon Sep 17 00:00:00 2001 From: Ivan Migalev Date: Sat, 28 Dec 2024 20:13:06 +0100 Subject: [PATCH 2/7] ImportLogic: do not omit public compiler-generated types --- src/Refasmer/Filters/PartialTypeFilterBase.cs | 2 ++ tests/Refasmer.Tests/IntegrationTestBase.cs | 18 +++++++++++------- tests/Refasmer.Tests/IntegrationTests.cs | 13 +++++++++++++ ...eratedClasses_omitNonApi=False.verified.txt | 3 +++ ...neratedClasses_omitNonApi=True.verified.txt | 3 +++ .../CompilerGeneratedClasses.cs | 9 +++++++++ 6 files changed, 41 insertions(+), 7 deletions(-) create mode 100644 tests/Refasmer.Tests/data/IntegrationTests.CheckCompilerGeneratedClasses_omitNonApi=False.verified.txt create mode 100644 tests/Refasmer.Tests/data/IntegrationTests.CheckCompilerGeneratedClasses_omitNonApi=True.verified.txt create mode 100644 tests/RefasmerTestAssembly/CompilerGeneratedClasses.cs diff --git a/src/Refasmer/Filters/PartialTypeFilterBase.cs b/src/Refasmer/Filters/PartialTypeFilterBase.cs index 92f3429..81f5e50 100644 --- a/src/Refasmer/Filters/PartialTypeFilterBase.cs +++ b/src/Refasmer/Filters/PartialTypeFilterBase.cs @@ -1,3 +1,4 @@ +using System.Reflection; using System.Reflection.Metadata; namespace JetBrains.Refasmer.Filters; @@ -12,6 +13,7 @@ public abstract class PartialTypeFilterBase(bool omitNonApiMembers) : IImportFil public virtual bool AllowImport(TypeDefinition type, MetadataReader reader) { + if (type.Attributes.HasFlag(TypeAttributes.Public)) return true; var isCompilerGenerated = AttributeCache.HasAttribute(reader, type, FullNames.CompilerGenerated); return !isCompilerGenerated; } diff --git a/tests/Refasmer.Tests/IntegrationTestBase.cs b/tests/Refasmer.Tests/IntegrationTestBase.cs index ea3244e..3c55854 100644 --- a/tests/Refasmer.Tests/IntegrationTestBase.cs +++ b/tests/Refasmer.Tests/IntegrationTestBase.cs @@ -72,21 +72,25 @@ protected static string RefasmTestAssembly(string assemblyPath, bool omitNonApiM } protected static Task VerifyTypeContent(string assemblyPath, string typeName) => - VerifyTypeContents(assemblyPath, [typeName], [typeName]); + VerifyTypeContents(assemblyPath, [typeName], parameters: [typeName]); - protected static Task VerifyTypeContents(string assemblyPath, string[] typeNames, object[]? parameters = null) + protected static Task VerifyTypeContents(string assemblyPath, string[] typeNames, bool assertTypeExists = true, object[]? parameters = null) { var assembly = AssemblyDefinition.ReadAssembly(assemblyPath); var printout = new StringBuilder(); foreach (var typeName in typeNames) { var type = assembly.MainModule.GetType(typeName); - Assert.That( - type, - Is.Not.Null, - $"Type \"{typeName}\" is not found in assembly \"{assemblyPath}\"."); + if (assertTypeExists) + { + Assert.That( + type, + Is.Not.Null, + $"Type \"{typeName}\" is not found in assembly \"{assemblyPath}\"."); + } - Printer.PrintType(type, printout); + if (type != null) + Printer.PrintType(type, printout); } var verifySettings = new VerifySettings(); diff --git a/tests/Refasmer.Tests/IntegrationTests.cs b/tests/Refasmer.Tests/IntegrationTests.cs index b5e037a..c30c29e 100644 --- a/tests/Refasmer.Tests/IntegrationTests.cs +++ b/tests/Refasmer.Tests/IntegrationTests.cs @@ -34,6 +34,19 @@ public async Task CheckRefasmedTypeOmitNonApi(string typeName) await VerifyTypeContent(resultAssembly, typeName); } + [TestCase(true)] + [TestCase(false)] + public async Task CheckCompilerGeneratedClasses(bool omitNonApi) + { + var assemblyPath = await BuildTestAssemblyWithInternalTypeInPublicApi(); + var resultAssembly = RefasmTestAssembly(assemblyPath, omitNonApiMembers: omitNonApi); + await VerifyTypeContents( + resultAssembly, + ["RefasmerTestAssembly.CompilerGeneratedPublicClass", "RefasmerTestAssembly.CompilerGeneratedInternalClass"], + assertTypeExists: false, + parameters: [omitNonApi]); + } + [Test] public async Task InternalTypeInPublicApi() { diff --git a/tests/Refasmer.Tests/data/IntegrationTests.CheckCompilerGeneratedClasses_omitNonApi=False.verified.txt b/tests/Refasmer.Tests/data/IntegrationTests.CheckCompilerGeneratedClasses_omitNonApi=False.verified.txt new file mode 100644 index 0000000..a2d4170 --- /dev/null +++ b/tests/Refasmer.Tests/data/IntegrationTests.CheckCompilerGeneratedClasses_omitNonApi=False.verified.txt @@ -0,0 +1,3 @@ +public type: RefasmerTestAssembly.CompilerGeneratedPublicClass +methods: +- .ctor(): System.Void: diff --git a/tests/Refasmer.Tests/data/IntegrationTests.CheckCompilerGeneratedClasses_omitNonApi=True.verified.txt b/tests/Refasmer.Tests/data/IntegrationTests.CheckCompilerGeneratedClasses_omitNonApi=True.verified.txt new file mode 100644 index 0000000..a2d4170 --- /dev/null +++ b/tests/Refasmer.Tests/data/IntegrationTests.CheckCompilerGeneratedClasses_omitNonApi=True.verified.txt @@ -0,0 +1,3 @@ +public type: RefasmerTestAssembly.CompilerGeneratedPublicClass +methods: +- .ctor(): System.Void: diff --git a/tests/RefasmerTestAssembly/CompilerGeneratedClasses.cs b/tests/RefasmerTestAssembly/CompilerGeneratedClasses.cs new file mode 100644 index 0000000..3aec539 --- /dev/null +++ b/tests/RefasmerTestAssembly/CompilerGeneratedClasses.cs @@ -0,0 +1,9 @@ +using System.Runtime.CompilerServices; + +namespace RefasmerTestAssembly; + +[CompilerGenerated] +public class CompilerGeneratedPublicClass; + +[CompilerGenerated] +internal class CompilerGeneratedInternalClass; From 269eb8c23f3deb5e4149ebc40d603f1eb7244b0e Mon Sep 17 00:00:00 2001 From: Ivan Migalev Date: Sat, 28 Dec 2024 20:15:21 +0100 Subject: [PATCH 3/7] Release: prepare v2.0.1-pre02 --- CHANGELOG.md | 1 + src/Directory.Build.props | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 831daf1..e45f2f0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a ## [Unreleased] ### Fixed - [#38: Internal types in public API break `omit-non-api-members=true`](https://github.com/JetBrains/Refasmer/issues/38). +- Fix regression since v2.0.0: public compiler-generated types are no longer ommitted from the refasmed assemblies. ## [2.0.0] - 2024-11-20 ### Changed diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 410ca59..197a230 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -1,6 +1,6 @@  - 2.0.1-pre01 + 2.0.1-pre02 Copyright © JetBrains 2024 Apache-2.0 From e816edc22ec54ccd713520e096cf2e33d29bb635 Mon Sep 17 00:00:00 2001 From: Ivan Migalev Date: Sun, 29 Dec 2024 17:21:27 +0100 Subject: [PATCH 4/7] IntegrationTestBase: migrate to TearDown NUnit's tests are not supposed to implement IDisposable. --- tests/Refasmer.Tests/IntegrationTestBase.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/Refasmer.Tests/IntegrationTestBase.cs b/tests/Refasmer.Tests/IntegrationTestBase.cs index 3c55854..4f988b5 100644 --- a/tests/Refasmer.Tests/IntegrationTestBase.cs +++ b/tests/Refasmer.Tests/IntegrationTestBase.cs @@ -5,7 +5,7 @@ namespace JetBrains.Refasmer.Tests; -public abstract class IntegrationTestBase : IDisposable +public abstract class IntegrationTestBase { protected static async Task BuildTestAssembly() { @@ -151,7 +151,8 @@ public void Dispose() protected static Outputs CollectConsoleOutput() => new(); - public void Dispose() + [TearDown] + public void TearDown() { Program.ResetArguments(); } From 7da8424bf42faf1ff03c1bceea332e47b2b6737a Mon Sep 17 00:00:00 2001 From: Ivan Migalev Date: Sun, 29 Dec 2024 17:50:58 +0100 Subject: [PATCH 5/7] (#38) ImportLogic: process inheritance as well --- src/Directory.Build.props | 2 +- src/Refasmer/Importer/ImportLogic.cs | 17 +++++++++++++++++ tests/Refasmer.Tests/IntegrationTests.cs | 13 ++++++++++--- ...onTests.InternalTypeInPublicApi.verified.txt | 5 ----- ...PublicClassDerivingFromInternal.verified.txt | 4 ++++ ...PublicClassImplementingInternal.verified.txt | 4 ++++ ...ublicClassWithInternalTypeInApi.verified.txt | 5 +++++ .../RefasmerTestAssembly/InternalClassInApi.cs | 14 ++++++++++++++ .../PublicClassWithInternalTypeInApi.cs | 8 -------- 9 files changed, 55 insertions(+), 17 deletions(-) delete mode 100644 tests/Refasmer.Tests/data/IntegrationTests.InternalTypeInPublicApi.verified.txt create mode 100644 tests/Refasmer.Tests/data/IntegrationTests.InternalTypeInPublicApi_mainClassName=PublicClassDerivingFromInternal.verified.txt create mode 100644 tests/Refasmer.Tests/data/IntegrationTests.InternalTypeInPublicApi_mainClassName=PublicClassImplementingInternal.verified.txt create mode 100644 tests/Refasmer.Tests/data/IntegrationTests.InternalTypeInPublicApi_mainClassName=PublicClassWithInternalTypeInApi.verified.txt create mode 100644 tests/RefasmerTestAssembly/InternalClassInApi.cs delete mode 100644 tests/RefasmerTestAssembly/PublicClassWithInternalTypeInApi.cs diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 197a230..19d729c 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -1,6 +1,6 @@  - 2.0.1-pre02 + 2.0.1-pre03 Copyright © JetBrains 2024 Apache-2.0 diff --git a/src/Refasmer/Importer/ImportLogic.cs b/src/Refasmer/Importer/ImportLogic.cs index 133400e..4ba9cfd 100644 --- a/src/Refasmer/Importer/ImportLogic.cs +++ b/src/Refasmer/Importer/ImportLogic.cs @@ -616,6 +616,23 @@ private IEnumerable CalculateInternalTypesToPreserve( var candidateTypes = new List(); var type = _reader.GetTypeDefinition(importedTypeHandle); var collector = new UsedTypeCollector(candidateTypes); + + var parentTypes = new List(); + if (!type.BaseType.IsNil) parentTypes.Add(type.BaseType); + foreach (var interfaceImpl in type.GetInterfaceImplementations()) + { + var @interface = _reader.GetInterfaceImplementation(interfaceImpl); + parentTypes.Add(@interface.Interface); + } + + foreach (var parentTypeHandle in parentTypes) + { + if (parentTypeHandle.Kind == HandleKind.TypeDefinition) + { + candidateTypes.Add((TypeDefinitionHandle)parentTypeHandle); + } + } + foreach (var fieldHandle in type.GetFields()) { var field = _reader.GetFieldDefinition(fieldHandle); diff --git a/tests/Refasmer.Tests/IntegrationTests.cs b/tests/Refasmer.Tests/IntegrationTests.cs index c30c29e..939b549 100644 --- a/tests/Refasmer.Tests/IntegrationTests.cs +++ b/tests/Refasmer.Tests/IntegrationTests.cs @@ -47,13 +47,20 @@ await VerifyTypeContents( parameters: [omitNonApi]); } - [Test] - public async Task InternalTypeInPublicApi() + [TestCase("PublicClassWithInternalTypeInApi", "Class1ToBeMarkedInternal")] + [TestCase("PublicClassDerivingFromInternal", "Class2ToBeMarkedInternal")] + [TestCase("PublicClassImplementingInternal", "InterfaceToBeMarkedInternal")] + public async Task InternalTypeInPublicApi(string mainClassName, string auxiliaryClassName) { var assemblyPath = await BuildTestAssemblyWithInternalTypeInPublicApi(); var resultAssembly = RefasmTestAssembly(assemblyPath, omitNonApiMembers: true); + + var fullMainClassName = $"RefasmerTestAssembly.{mainClassName}"; + var fullAuxiliaryClassName = $"RefasmerTestAssembly.{auxiliaryClassName}"; + await VerifyTypeContents( resultAssembly, - ["RefasmerTestAssembly.PublicClassWithInternalTypeInApi", "RefasmerTestAssembly.ClassToBeMarkedInternal"]); + [fullMainClassName, fullAuxiliaryClassName], + parameters: [mainClassName]); } } diff --git a/tests/Refasmer.Tests/data/IntegrationTests.InternalTypeInPublicApi.verified.txt b/tests/Refasmer.Tests/data/IntegrationTests.InternalTypeInPublicApi.verified.txt deleted file mode 100644 index f552028..0000000 --- a/tests/Refasmer.Tests/data/IntegrationTests.InternalTypeInPublicApi.verified.txt +++ /dev/null @@ -1,5 +0,0 @@ -public type: RefasmerTestAssembly.PublicClassWithInternalTypeInApi -methods: -- Accept(RefasmerTestAssembly.ClassToBeMarkedInternal argument): System.Void: -- .ctor(): System.Void: -internal type: RefasmerTestAssembly.ClassToBeMarkedInternal diff --git a/tests/Refasmer.Tests/data/IntegrationTests.InternalTypeInPublicApi_mainClassName=PublicClassDerivingFromInternal.verified.txt b/tests/Refasmer.Tests/data/IntegrationTests.InternalTypeInPublicApi_mainClassName=PublicClassDerivingFromInternal.verified.txt new file mode 100644 index 0000000..0813c7b --- /dev/null +++ b/tests/Refasmer.Tests/data/IntegrationTests.InternalTypeInPublicApi_mainClassName=PublicClassDerivingFromInternal.verified.txt @@ -0,0 +1,4 @@ +public type: RefasmerTestAssembly.PublicClassDerivingFromInternal +methods: +- .ctor(): System.Void: +internal type: RefasmerTestAssembly.Class2ToBeMarkedInternal diff --git a/tests/Refasmer.Tests/data/IntegrationTests.InternalTypeInPublicApi_mainClassName=PublicClassImplementingInternal.verified.txt b/tests/Refasmer.Tests/data/IntegrationTests.InternalTypeInPublicApi_mainClassName=PublicClassImplementingInternal.verified.txt new file mode 100644 index 0000000..c287ddf --- /dev/null +++ b/tests/Refasmer.Tests/data/IntegrationTests.InternalTypeInPublicApi_mainClassName=PublicClassImplementingInternal.verified.txt @@ -0,0 +1,4 @@ +public type: RefasmerTestAssembly.PublicClassImplementingInternal +methods: +- .ctor(): System.Void: +internal type: RefasmerTestAssembly.InterfaceToBeMarkedInternal diff --git a/tests/Refasmer.Tests/data/IntegrationTests.InternalTypeInPublicApi_mainClassName=PublicClassWithInternalTypeInApi.verified.txt b/tests/Refasmer.Tests/data/IntegrationTests.InternalTypeInPublicApi_mainClassName=PublicClassWithInternalTypeInApi.verified.txt new file mode 100644 index 0000000..459e775 --- /dev/null +++ b/tests/Refasmer.Tests/data/IntegrationTests.InternalTypeInPublicApi_mainClassName=PublicClassWithInternalTypeInApi.verified.txt @@ -0,0 +1,5 @@ +public type: RefasmerTestAssembly.PublicClassWithInternalTypeInApi +methods: +- Accept(RefasmerTestAssembly.Class1ToBeMarkedInternal argument): System.Void: +- .ctor(): System.Void: +internal type: RefasmerTestAssembly.Class1ToBeMarkedInternal diff --git a/tests/RefasmerTestAssembly/InternalClassInApi.cs b/tests/RefasmerTestAssembly/InternalClassInApi.cs new file mode 100644 index 0000000..ee17961 --- /dev/null +++ b/tests/RefasmerTestAssembly/InternalClassInApi.cs @@ -0,0 +1,14 @@ +namespace RefasmerTestAssembly; + +// Post-processed and converted to internal by tests: +public class Class1ToBeMarkedInternal; +public class Class2ToBeMarkedInternal; +public class InterfaceToBeMarkedInternal; + +public class PublicClassWithInternalTypeInApi +{ + public void Accept(Class1ToBeMarkedInternal argument) {} +} + +public class PublicClassDerivingFromInternal : Class2ToBeMarkedInternal; +public class PublicClassImplementingInternal : InterfaceToBeMarkedInternal; diff --git a/tests/RefasmerTestAssembly/PublicClassWithInternalTypeInApi.cs b/tests/RefasmerTestAssembly/PublicClassWithInternalTypeInApi.cs deleted file mode 100644 index 7d6860c..0000000 --- a/tests/RefasmerTestAssembly/PublicClassWithInternalTypeInApi.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace RefasmerTestAssembly; - -public class PublicClassWithInternalTypeInApi -{ - public void Accept(ClassToBeMarkedInternal argument) {} -} - -public class ClassToBeMarkedInternal; // post-processed by tests From c91d13d42e2aedd5d88e7ee41b88f4a7891bf1e7 Mon Sep 17 00:00:00 2001 From: Ivan Migalev Date: Sun, 29 Dec 2024 18:30:18 +0100 Subject: [PATCH 6/7] (#38) ImportLogic: process generic parameters in type signatures --- src/Directory.Build.props | 2 +- src/Refasmer/Importer/ImportLogic.cs | 16 +++++++++---- tests/Refasmer.Tests/IntegrationTests.cs | 9 +++---- tests/Refasmer.Tests/Printer.cs | 24 +++++++++++++++---- ...erTestAssembly.BlittableGraph.verified.txt | 2 +- ...ttableStructWithPrivateFields.verified.txt | 2 +- ...y.EmptyStructWithStaticMember.verified.txt | 2 +- ...estAssembly.NonBlittableGraph.verified.txt | 2 +- ...ttableStructWithPrivateFields.verified.txt | 2 +- ...onEmptyStructWithStaticMember.verified.txt | 2 +- ....PublicClassWithPrivateFields.verified.txt | 2 +- ...PublicStructWithPrivateFields.verified.txt | 2 +- ....StructWithNestedPrivateTypes.verified.txt | 4 ++-- ...nsafeClassWithFunctionPointer.verified.txt | 2 +- ...estAssembly.NonBlittableGraph.verified.txt | 6 ++--- ...blicClassImplementingInternal.verified.txt | 4 ++-- ...lassWithInternalInterfaceImpl.verified.txt | 9 +++++++ .../InternalClassInApi.cs | 16 +++++++++++-- 18 files changed, 76 insertions(+), 32 deletions(-) create mode 100644 tests/Refasmer.Tests/data/IntegrationTests.InternalTypeInPublicApi_mainClassName=PublicClassWithInternalInterfaceImpl.verified.txt diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 19d729c..6746357 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -1,6 +1,6 @@  - 2.0.1-pre03 + 2.0.1-pre04 Copyright © JetBrains 2024 Apache-2.0 diff --git a/src/Refasmer/Importer/ImportLogic.cs b/src/Refasmer/Importer/ImportLogic.cs index 4ba9cfd..2ee152d 100644 --- a/src/Refasmer/Importer/ImportLogic.cs +++ b/src/Refasmer/Importer/ImportLogic.cs @@ -619,17 +619,23 @@ private IEnumerable CalculateInternalTypesToPreserve( var parentTypes = new List(); if (!type.BaseType.IsNil) parentTypes.Add(type.BaseType); - foreach (var interfaceImpl in type.GetInterfaceImplementations()) + foreach (var interfaceImplHandle in type.GetInterfaceImplementations()) { - var @interface = _reader.GetInterfaceImplementation(interfaceImpl); - parentTypes.Add(@interface.Interface); + var interfaceImpl = _reader.GetInterfaceImplementation(interfaceImplHandle); + parentTypes.Add(interfaceImpl.Interface); } foreach (var parentTypeHandle in parentTypes) { - if (parentTypeHandle.Kind == HandleKind.TypeDefinition) + switch (parentTypeHandle.Kind) { - candidateTypes.Add((TypeDefinitionHandle)parentTypeHandle); + case HandleKind.TypeDefinition: + candidateTypes.Add((TypeDefinitionHandle)parentTypeHandle); + break; + case HandleKind.TypeSpecification: + var specification = _reader.GetTypeSpecification((TypeSpecificationHandle)parentTypeHandle); + AcceptTypeSignature(specification.Signature, collector); + break; } } diff --git a/tests/Refasmer.Tests/IntegrationTests.cs b/tests/Refasmer.Tests/IntegrationTests.cs index 939b549..2256709 100644 --- a/tests/Refasmer.Tests/IntegrationTests.cs +++ b/tests/Refasmer.Tests/IntegrationTests.cs @@ -49,18 +49,19 @@ await VerifyTypeContents( [TestCase("PublicClassWithInternalTypeInApi", "Class1ToBeMarkedInternal")] [TestCase("PublicClassDerivingFromInternal", "Class2ToBeMarkedInternal")] - [TestCase("PublicClassImplementingInternal", "InterfaceToBeMarkedInternal")] - public async Task InternalTypeInPublicApi(string mainClassName, string auxiliaryClassName) + [TestCase("PublicClassImplementingInternal", "IInterface1ToBeMarkedInternal")] + [TestCase("PublicClassWithInternalInterfaceImpl", "Class3ToBeMarkedInternal,IInterface2ToBeMarkedInternal`1")] + public async Task InternalTypeInPublicApi(string mainClassName, string auxiliaryClassNames) { var assemblyPath = await BuildTestAssemblyWithInternalTypeInPublicApi(); var resultAssembly = RefasmTestAssembly(assemblyPath, omitNonApiMembers: true); var fullMainClassName = $"RefasmerTestAssembly.{mainClassName}"; - var fullAuxiliaryClassName = $"RefasmerTestAssembly.{auxiliaryClassName}"; + var fullAuxiliaryClassNames = auxiliaryClassNames.Split(',').Select(x => $"RefasmerTestAssembly.{x}"); await VerifyTypeContents( resultAssembly, - [fullMainClassName, fullAuxiliaryClassName], + [fullMainClassName, ..fullAuxiliaryClassNames], parameters: [mainClassName]); } } diff --git a/tests/Refasmer.Tests/Printer.cs b/tests/Refasmer.Tests/Printer.cs index 36a0a9c..d2ec172 100644 --- a/tests/Refasmer.Tests/Printer.cs +++ b/tests/Refasmer.Tests/Printer.cs @@ -8,7 +8,8 @@ public static class Printer public static void PrintType(TypeDefinition type, StringBuilder printout, string indent = "") { var access = GetAccessString(type); - printout.AppendLine($"{indent}{access} type: {type.FullName}"); + var typeKind = GetTypeKindString(type); + printout.AppendLine($"{indent}{access} {typeKind}: {type.FullName}"); if (type.HasFields) { printout.AppendLine($"{indent}fields:"); @@ -34,10 +35,15 @@ public static void PrintType(TypeDefinition type, StringBuilder printout, string } } - printout.AppendLine($"{indent}): {method.ReturnType}:"); - foreach (var instruction in method.Body.Instructions) + printout.AppendLine($"): {method.ReturnType}:"); + if (method.IsAbstract) + printout.AppendLine($"{indent} - "); + else { - printout.AppendLine($"{indent} - {instruction}"); + foreach (var instruction in method.Body.Instructions) + { + printout.AppendLine($"{indent} - {instruction}"); + } } } } @@ -62,4 +68,14 @@ private static string GetAccessString(TypeDefinition type) if (type.IsNestedFamilyAndAssembly) return "private protected"; return "internal"; } + + private static string GetTypeKindString(TypeDefinition typeDefinition) + { + var result = new StringBuilder(); + if (typeDefinition.IsInterface) result.Append("interface"); + else if (typeDefinition.IsAbstract) result.Append("abstract "); + if (typeDefinition.IsValueType) result.Append("struct"); + else if (typeDefinition.IsClass) result.Append("class"); + return result.ToString(); + } } diff --git a/tests/Refasmer.Tests/data/IntegrationTests.CheckRefasmedTypeOmitNonApi_typeName=RefasmerTestAssembly.BlittableGraph.verified.txt b/tests/Refasmer.Tests/data/IntegrationTests.CheckRefasmedTypeOmitNonApi_typeName=RefasmerTestAssembly.BlittableGraph.verified.txt index 5d625ae..1b156e7 100644 --- a/tests/Refasmer.Tests/data/IntegrationTests.CheckRefasmedTypeOmitNonApi_typeName=RefasmerTestAssembly.BlittableGraph.verified.txt +++ b/tests/Refasmer.Tests/data/IntegrationTests.CheckRefasmedTypeOmitNonApi_typeName=RefasmerTestAssembly.BlittableGraph.verified.txt @@ -1,3 +1,3 @@ -public type: RefasmerTestAssembly.BlittableGraph +public struct: RefasmerTestAssembly.BlittableGraph fields: - : System.Int32 diff --git a/tests/Refasmer.Tests/data/IntegrationTests.CheckRefasmedTypeOmitNonApi_typeName=RefasmerTestAssembly.BlittableStructWithPrivateFields.verified.txt b/tests/Refasmer.Tests/data/IntegrationTests.CheckRefasmedTypeOmitNonApi_typeName=RefasmerTestAssembly.BlittableStructWithPrivateFields.verified.txt index 2d4e000..f803a52 100644 --- a/tests/Refasmer.Tests/data/IntegrationTests.CheckRefasmedTypeOmitNonApi_typeName=RefasmerTestAssembly.BlittableStructWithPrivateFields.verified.txt +++ b/tests/Refasmer.Tests/data/IntegrationTests.CheckRefasmedTypeOmitNonApi_typeName=RefasmerTestAssembly.BlittableStructWithPrivateFields.verified.txt @@ -1,3 +1,3 @@ -public type: RefasmerTestAssembly.BlittableStructWithPrivateFields +public struct: RefasmerTestAssembly.BlittableStructWithPrivateFields fields: - : System.Int32 diff --git a/tests/Refasmer.Tests/data/IntegrationTests.CheckRefasmedTypeOmitNonApi_typeName=RefasmerTestAssembly.EmptyStructWithStaticMember.verified.txt b/tests/Refasmer.Tests/data/IntegrationTests.CheckRefasmedTypeOmitNonApi_typeName=RefasmerTestAssembly.EmptyStructWithStaticMember.verified.txt index cb9c757..fb20c2b 100644 --- a/tests/Refasmer.Tests/data/IntegrationTests.CheckRefasmedTypeOmitNonApi_typeName=RefasmerTestAssembly.EmptyStructWithStaticMember.verified.txt +++ b/tests/Refasmer.Tests/data/IntegrationTests.CheckRefasmedTypeOmitNonApi_typeName=RefasmerTestAssembly.EmptyStructWithStaticMember.verified.txt @@ -1 +1 @@ -public type: RefasmerTestAssembly.EmptyStructWithStaticMember +public struct: RefasmerTestAssembly.EmptyStructWithStaticMember diff --git a/tests/Refasmer.Tests/data/IntegrationTests.CheckRefasmedTypeOmitNonApi_typeName=RefasmerTestAssembly.NonBlittableGraph.verified.txt b/tests/Refasmer.Tests/data/IntegrationTests.CheckRefasmedTypeOmitNonApi_typeName=RefasmerTestAssembly.NonBlittableGraph.verified.txt index 2b70304..a9e6a31 100644 --- a/tests/Refasmer.Tests/data/IntegrationTests.CheckRefasmedTypeOmitNonApi_typeName=RefasmerTestAssembly.NonBlittableGraph.verified.txt +++ b/tests/Refasmer.Tests/data/IntegrationTests.CheckRefasmedTypeOmitNonApi_typeName=RefasmerTestAssembly.NonBlittableGraph.verified.txt @@ -1,3 +1,3 @@ -public type: RefasmerTestAssembly.NonBlittableGraph +public struct: RefasmerTestAssembly.NonBlittableGraph fields: - : System.Int32 diff --git a/tests/Refasmer.Tests/data/IntegrationTests.CheckRefasmedTypeOmitNonApi_typeName=RefasmerTestAssembly.NonBlittableStructWithPrivateFields.verified.txt b/tests/Refasmer.Tests/data/IntegrationTests.CheckRefasmedTypeOmitNonApi_typeName=RefasmerTestAssembly.NonBlittableStructWithPrivateFields.verified.txt index 3e5a629..dd46266 100644 --- a/tests/Refasmer.Tests/data/IntegrationTests.CheckRefasmedTypeOmitNonApi_typeName=RefasmerTestAssembly.NonBlittableStructWithPrivateFields.verified.txt +++ b/tests/Refasmer.Tests/data/IntegrationTests.CheckRefasmedTypeOmitNonApi_typeName=RefasmerTestAssembly.NonBlittableStructWithPrivateFields.verified.txt @@ -1,3 +1,3 @@ -public type: RefasmerTestAssembly.NonBlittableStructWithPrivateFields +public struct: RefasmerTestAssembly.NonBlittableStructWithPrivateFields fields: - : System.Int32 diff --git a/tests/Refasmer.Tests/data/IntegrationTests.CheckRefasmedTypeOmitNonApi_typeName=RefasmerTestAssembly.NonEmptyStructWithStaticMember.verified.txt b/tests/Refasmer.Tests/data/IntegrationTests.CheckRefasmedTypeOmitNonApi_typeName=RefasmerTestAssembly.NonEmptyStructWithStaticMember.verified.txt index a5eb51c..e62402a 100644 --- a/tests/Refasmer.Tests/data/IntegrationTests.CheckRefasmedTypeOmitNonApi_typeName=RefasmerTestAssembly.NonEmptyStructWithStaticMember.verified.txt +++ b/tests/Refasmer.Tests/data/IntegrationTests.CheckRefasmedTypeOmitNonApi_typeName=RefasmerTestAssembly.NonEmptyStructWithStaticMember.verified.txt @@ -1,3 +1,3 @@ -public type: RefasmerTestAssembly.NonEmptyStructWithStaticMember +public struct: RefasmerTestAssembly.NonEmptyStructWithStaticMember fields: - : System.Int32 diff --git a/tests/Refasmer.Tests/data/IntegrationTests.CheckRefasmedTypeOmitNonApi_typeName=RefasmerTestAssembly.PublicClassWithPrivateFields.verified.txt b/tests/Refasmer.Tests/data/IntegrationTests.CheckRefasmedTypeOmitNonApi_typeName=RefasmerTestAssembly.PublicClassWithPrivateFields.verified.txt index b3096b0..059e029 100644 --- a/tests/Refasmer.Tests/data/IntegrationTests.CheckRefasmedTypeOmitNonApi_typeName=RefasmerTestAssembly.PublicClassWithPrivateFields.verified.txt +++ b/tests/Refasmer.Tests/data/IntegrationTests.CheckRefasmedTypeOmitNonApi_typeName=RefasmerTestAssembly.PublicClassWithPrivateFields.verified.txt @@ -1,4 +1,4 @@ -public type: RefasmerTestAssembly.PublicClassWithPrivateFields +public class: RefasmerTestAssembly.PublicClassWithPrivateFields fields: - PublicInt: System.Int32 methods: diff --git a/tests/Refasmer.Tests/data/IntegrationTests.CheckRefasmedTypeOmitNonApi_typeName=RefasmerTestAssembly.PublicStructWithPrivateFields.verified.txt b/tests/Refasmer.Tests/data/IntegrationTests.CheckRefasmedTypeOmitNonApi_typeName=RefasmerTestAssembly.PublicStructWithPrivateFields.verified.txt index ed60ee4..999eb30 100644 --- a/tests/Refasmer.Tests/data/IntegrationTests.CheckRefasmedTypeOmitNonApi_typeName=RefasmerTestAssembly.PublicStructWithPrivateFields.verified.txt +++ b/tests/Refasmer.Tests/data/IntegrationTests.CheckRefasmedTypeOmitNonApi_typeName=RefasmerTestAssembly.PublicStructWithPrivateFields.verified.txt @@ -1,3 +1,3 @@ -public type: RefasmerTestAssembly.PublicStructWithPrivateFields +public struct: RefasmerTestAssembly.PublicStructWithPrivateFields fields: - PublicInt: System.Int32 diff --git a/tests/Refasmer.Tests/data/IntegrationTests.CheckRefasmedTypeOmitNonApi_typeName=RefasmerTestAssembly.StructWithNestedPrivateTypes.verified.txt b/tests/Refasmer.Tests/data/IntegrationTests.CheckRefasmedTypeOmitNonApi_typeName=RefasmerTestAssembly.StructWithNestedPrivateTypes.verified.txt index 08cefb4..768d907 100644 --- a/tests/Refasmer.Tests/data/IntegrationTests.CheckRefasmedTypeOmitNonApi_typeName=RefasmerTestAssembly.StructWithNestedPrivateTypes.verified.txt +++ b/tests/Refasmer.Tests/data/IntegrationTests.CheckRefasmedTypeOmitNonApi_typeName=RefasmerTestAssembly.StructWithNestedPrivateTypes.verified.txt @@ -1,7 +1,7 @@ -public type: RefasmerTestAssembly.StructWithNestedPrivateTypes +public struct: RefasmerTestAssembly.StructWithNestedPrivateTypes fields: - : System.Int32 types: - internal type: RefasmerTestAssembly.StructWithNestedPrivateTypes/UnusedPublicStruct + internal struct: RefasmerTestAssembly.StructWithNestedPrivateTypes/UnusedPublicStruct fields: - : System.Int32 diff --git a/tests/Refasmer.Tests/data/IntegrationTests.CheckRefasmedTypeOmitNonApi_typeName=RefasmerTestAssembly.UnsafeClassWithFunctionPointer.verified.txt b/tests/Refasmer.Tests/data/IntegrationTests.CheckRefasmedTypeOmitNonApi_typeName=RefasmerTestAssembly.UnsafeClassWithFunctionPointer.verified.txt index 679ec12..d81374a 100644 --- a/tests/Refasmer.Tests/data/IntegrationTests.CheckRefasmedTypeOmitNonApi_typeName=RefasmerTestAssembly.UnsafeClassWithFunctionPointer.verified.txt +++ b/tests/Refasmer.Tests/data/IntegrationTests.CheckRefasmedTypeOmitNonApi_typeName=RefasmerTestAssembly.UnsafeClassWithFunctionPointer.verified.txt @@ -1,4 +1,4 @@ -public type: RefasmerTestAssembly.UnsafeClassWithFunctionPointer +public class: RefasmerTestAssembly.UnsafeClassWithFunctionPointer methods: - MethodWithFunctionPointer(method System.Void *() functionPointer): System.Void: - .ctor(): System.Void: diff --git a/tests/Refasmer.Tests/data/IntegrationTests.CheckRefasmedType_typeName=RefasmerTestAssembly.NonBlittableGraph.verified.txt b/tests/Refasmer.Tests/data/IntegrationTests.CheckRefasmedType_typeName=RefasmerTestAssembly.NonBlittableGraph.verified.txt index 940bc52..2cd2c1c 100644 --- a/tests/Refasmer.Tests/data/IntegrationTests.CheckRefasmedType_typeName=RefasmerTestAssembly.NonBlittableGraph.verified.txt +++ b/tests/Refasmer.Tests/data/IntegrationTests.CheckRefasmedType_typeName=RefasmerTestAssembly.NonBlittableGraph.verified.txt @@ -1,11 +1,11 @@ -public type: RefasmerTestAssembly.NonBlittableGraph +public struct: RefasmerTestAssembly.NonBlittableGraph fields: - x: RefasmerTestAssembly.NonBlittableGraph/DubiouslyBlittableType types: - private type: RefasmerTestAssembly.NonBlittableGraph/DubiouslyBlittableType + private struct: RefasmerTestAssembly.NonBlittableGraph/DubiouslyBlittableType fields: - x: RefasmerTestAssembly.NonBlittableGraph/DubiouslyBlittableType/NonBlittableType types: - private type: RefasmerTestAssembly.NonBlittableGraph/DubiouslyBlittableType/NonBlittableType + private struct: RefasmerTestAssembly.NonBlittableGraph/DubiouslyBlittableType/NonBlittableType fields: - x: System.String diff --git a/tests/Refasmer.Tests/data/IntegrationTests.InternalTypeInPublicApi_mainClassName=PublicClassImplementingInternal.verified.txt b/tests/Refasmer.Tests/data/IntegrationTests.InternalTypeInPublicApi_mainClassName=PublicClassImplementingInternal.verified.txt index c287ddf..6beb1d5 100644 --- a/tests/Refasmer.Tests/data/IntegrationTests.InternalTypeInPublicApi_mainClassName=PublicClassImplementingInternal.verified.txt +++ b/tests/Refasmer.Tests/data/IntegrationTests.InternalTypeInPublicApi_mainClassName=PublicClassImplementingInternal.verified.txt @@ -1,4 +1,4 @@ -public type: RefasmerTestAssembly.PublicClassImplementingInternal +public class: RefasmerTestAssembly.PublicClassImplementingInternal methods: - .ctor(): System.Void: -internal type: RefasmerTestAssembly.InterfaceToBeMarkedInternal +internal interface: RefasmerTestAssembly.IInterface1ToBeMarkedInternal diff --git a/tests/Refasmer.Tests/data/IntegrationTests.InternalTypeInPublicApi_mainClassName=PublicClassWithInternalInterfaceImpl.verified.txt b/tests/Refasmer.Tests/data/IntegrationTests.InternalTypeInPublicApi_mainClassName=PublicClassWithInternalInterfaceImpl.verified.txt new file mode 100644 index 0000000..ce5a3ce --- /dev/null +++ b/tests/Refasmer.Tests/data/IntegrationTests.InternalTypeInPublicApi_mainClassName=PublicClassWithInternalInterfaceImpl.verified.txt @@ -0,0 +1,9 @@ +public class: RefasmerTestAssembly.PublicClassWithInternalInterfaceImpl +methods: +- RefasmerTestAssembly.IInterface2ToBeMarkedInternal.Foo(): RefasmerTestAssembly.Class3ToBeMarkedInternal: +- .ctor(): System.Void: +internal class: RefasmerTestAssembly.Class3ToBeMarkedInternal +public interface: RefasmerTestAssembly.IInterface2ToBeMarkedInternal`1 +methods: +- Foo(): T: + - diff --git a/tests/RefasmerTestAssembly/InternalClassInApi.cs b/tests/RefasmerTestAssembly/InternalClassInApi.cs index ee17961..67e6d92 100644 --- a/tests/RefasmerTestAssembly/InternalClassInApi.cs +++ b/tests/RefasmerTestAssembly/InternalClassInApi.cs @@ -1,9 +1,16 @@ +using System; + namespace RefasmerTestAssembly; // Post-processed and converted to internal by tests: public class Class1ToBeMarkedInternal; public class Class2ToBeMarkedInternal; -public class InterfaceToBeMarkedInternal; +public class Class3ToBeMarkedInternal; +public interface IInterface1ToBeMarkedInternal; +public interface IInterface2ToBeMarkedInternal +{ + T Foo(); +} public class PublicClassWithInternalTypeInApi { @@ -11,4 +18,9 @@ public void Accept(Class1ToBeMarkedInternal argument) {} } public class PublicClassDerivingFromInternal : Class2ToBeMarkedInternal; -public class PublicClassImplementingInternal : InterfaceToBeMarkedInternal; +public class PublicClassImplementingInternal : IInterface1ToBeMarkedInternal; + +public class PublicClassWithInternalInterfaceImpl : IInterface2ToBeMarkedInternal +{ + Class3ToBeMarkedInternal IInterface2ToBeMarkedInternal.Foo() => throw new Exception("123"); +} \ No newline at end of file From 4099faf8465c4f8a835fd3f0551a2571577eef25 Mon Sep 17 00:00:00 2001 From: Ivan Migalev Date: Sun, 29 Dec 2024 19:37:57 +0100 Subject: [PATCH 7/7] (#38) ImportLogic: fix import for explicit methods of internal interfaces --- src/Directory.Build.props | 2 +- src/Refasmer/Importer/ImportLogic.cs | 24 ++++++++++----- tests/Refasmer.Tests/IntegrationTestBase.cs | 3 +- tests/Refasmer.Tests/IntegrationTests.cs | 2 ++ tests/Refasmer.Tests/Printer.cs | 15 ++++++++++ ...blicClassImplementingInternal.verified.txt | 1 + ...lassWithInternalInterfaceImpl.verified.txt | 7 ++--- ...ithInternalTypeInExplicitImpl.verified.txt | 5 ++++ ...nalClassInApi.cs => InternalTypesInApi.cs} | 29 +++++++++++++------ 9 files changed, 65 insertions(+), 23 deletions(-) create mode 100644 tests/Refasmer.Tests/data/IntegrationTests.InternalTypeInPublicApi_mainClassName=PublicClassWithInternalTypeInExplicitImpl.verified.txt rename tests/RefasmerTestAssembly/{InternalClassInApi.cs => InternalTypesInApi.cs} (70%) diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 6746357..6b2fb62 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -1,6 +1,6 @@  - 2.0.1-pre04 + 2.0.1-pre05 Copyright © JetBrains 2024 Apache-2.0 diff --git a/src/Refasmer/Importer/ImportLogic.cs b/src/Refasmer/Importer/ImportLogic.cs index 2ee152d..888074f 100644 --- a/src/Refasmer/Importer/ImportLogic.cs +++ b/src/Refasmer/Importer/ImportLogic.cs @@ -87,17 +87,13 @@ private TypeDefinitionHandle ImportTypeDefinitionSkeleton(TypeDefinitionHandle s if (!forcePreservePrivateFields) PostProcessSkippedValueTypeFields(skippedInstanceFields!, importedInstanceFields!); - var implementations = src.GetMethodImplementations() - .Select(_reader.GetMethodImplementation) - .Where(mi => AllowImportType(_reader.GetMethodClass(mi.MethodDeclaration))) - .Select(mi => (MethodDefinitionHandle)mi.MethodBody) - .ToImmutableHashSet(); + var implementations = GetAllowedInterfaceMethodImplementations(src); foreach (var srcMethodHandle in src.GetMethods()) { var srcMethod = _reader.GetMethodDefinition(srcMethodHandle); - if (!implementations.Contains(srcMethodHandle) && Filter?.AllowImport(srcMethod, _reader) == false) + if (!AllowImportMethod(implementations, srcMethodHandle, srcMethod)) { Trace?.Invoke($"Not imported {_reader.ToString(srcMethod)}"); continue; @@ -406,6 +402,19 @@ 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 bool AllowImportMethod( + IImmutableSet implementations, + MethodDefinitionHandle methodHandle, + MethodDefinition method) => + !implementations.Contains(methodHandle) && (Filter == null || Filter.AllowImport(method, _reader)); + public ReservedBlob Import() { if (_reader.IsAssembly) @@ -646,10 +655,11 @@ private IEnumerable CalculateInternalTypesToPreserve( AcceptFieldSignature(field, collector); } + var methodImplementations = GetAllowedInterfaceMethodImplementations(type); foreach (var methodHandle in type.GetMethods()) { var method = _reader.GetMethodDefinition(methodHandle); - if (Filter == null || Filter.AllowImport(method, _reader)) + if (AllowImportMethod(methodImplementations, methodHandle, method)) AcceptMethodSignature(method, collector); } diff --git a/tests/Refasmer.Tests/IntegrationTestBase.cs b/tests/Refasmer.Tests/IntegrationTestBase.cs index 4f988b5..5de5758 100644 --- a/tests/Refasmer.Tests/IntegrationTestBase.cs +++ b/tests/Refasmer.Tests/IntegrationTestBase.cs @@ -107,7 +107,8 @@ private static void MarkTypesInternal(string inputAssemblyPath, string outputAss var assemblyDefinition = AssemblyDefinition.ReadAssembly(inputAssemblyPath); foreach (var type in assemblyDefinition.MainModule.Types) { - if (type.IsPublic && type.Name.EndsWith(typeNameSuffix)) + var friendlyTypeName = type.Name.Split('`')[0]; // strip generic suffix + if (type.IsPublic && friendlyTypeName.EndsWith(typeNameSuffix)) { type.IsPublic = false; type.IsNotPublic = true; diff --git a/tests/Refasmer.Tests/IntegrationTests.cs b/tests/Refasmer.Tests/IntegrationTests.cs index 2256709..cea0d85 100644 --- a/tests/Refasmer.Tests/IntegrationTests.cs +++ b/tests/Refasmer.Tests/IntegrationTests.cs @@ -51,6 +51,7 @@ await VerifyTypeContents( [TestCase("PublicClassDerivingFromInternal", "Class2ToBeMarkedInternal")] [TestCase("PublicClassImplementingInternal", "IInterface1ToBeMarkedInternal")] [TestCase("PublicClassWithInternalInterfaceImpl", "Class3ToBeMarkedInternal,IInterface2ToBeMarkedInternal`1")] + [TestCase("PublicClassWithInternalTypeInExplicitImpl", "IInterface3")] public async Task InternalTypeInPublicApi(string mainClassName, string auxiliaryClassNames) { var assemblyPath = await BuildTestAssemblyWithInternalTypeInPublicApi(); @@ -62,6 +63,7 @@ public async Task InternalTypeInPublicApi(string mainClassName, string auxiliary await VerifyTypeContents( resultAssembly, [fullMainClassName, ..fullAuxiliaryClassNames], + assertTypeExists: false, parameters: [mainClassName]); } } diff --git a/tests/Refasmer.Tests/Printer.cs b/tests/Refasmer.Tests/Printer.cs index d2ec172..f6f0ad5 100644 --- a/tests/Refasmer.Tests/Printer.cs +++ b/tests/Refasmer.Tests/Printer.cs @@ -10,6 +10,21 @@ public static void PrintType(TypeDefinition type, StringBuilder printout, string var access = GetAccessString(type); var typeKind = GetTypeKindString(type); printout.AppendLine($"{indent}{access} {typeKind}: {type.FullName}"); + + var baseType = type.BaseType; + if (baseType != null && baseType.FullName != "System.Object" && baseType.FullName != "System.ValueType") + { + printout.AppendLine($"{indent} - base type: {baseType.FullName}"); + } + + if (type.HasInterfaces) + { + foreach (var @interface in type.Interfaces) + { + printout.AppendLine($"{indent} - interface impl: {@interface.InterfaceType.FullName}"); + } + } + if (type.HasFields) { printout.AppendLine($"{indent}fields:"); diff --git a/tests/Refasmer.Tests/data/IntegrationTests.InternalTypeInPublicApi_mainClassName=PublicClassImplementingInternal.verified.txt b/tests/Refasmer.Tests/data/IntegrationTests.InternalTypeInPublicApi_mainClassName=PublicClassImplementingInternal.verified.txt index 6beb1d5..3cdda3d 100644 --- a/tests/Refasmer.Tests/data/IntegrationTests.InternalTypeInPublicApi_mainClassName=PublicClassImplementingInternal.verified.txt +++ b/tests/Refasmer.Tests/data/IntegrationTests.InternalTypeInPublicApi_mainClassName=PublicClassImplementingInternal.verified.txt @@ -1,4 +1,5 @@ public class: RefasmerTestAssembly.PublicClassImplementingInternal + - interface impl: RefasmerTestAssembly.IInterface1ToBeMarkedInternal methods: - .ctor(): System.Void: internal interface: RefasmerTestAssembly.IInterface1ToBeMarkedInternal diff --git a/tests/Refasmer.Tests/data/IntegrationTests.InternalTypeInPublicApi_mainClassName=PublicClassWithInternalInterfaceImpl.verified.txt b/tests/Refasmer.Tests/data/IntegrationTests.InternalTypeInPublicApi_mainClassName=PublicClassWithInternalInterfaceImpl.verified.txt index ce5a3ce..26f3343 100644 --- a/tests/Refasmer.Tests/data/IntegrationTests.InternalTypeInPublicApi_mainClassName=PublicClassWithInternalInterfaceImpl.verified.txt +++ b/tests/Refasmer.Tests/data/IntegrationTests.InternalTypeInPublicApi_mainClassName=PublicClassWithInternalInterfaceImpl.verified.txt @@ -1,9 +1,6 @@ public class: RefasmerTestAssembly.PublicClassWithInternalInterfaceImpl + - interface impl: RefasmerTestAssembly.IInterface2ToBeMarkedInternal`1 methods: -- RefasmerTestAssembly.IInterface2ToBeMarkedInternal.Foo(): RefasmerTestAssembly.Class3ToBeMarkedInternal: - .ctor(): System.Void: internal class: RefasmerTestAssembly.Class3ToBeMarkedInternal -public interface: RefasmerTestAssembly.IInterface2ToBeMarkedInternal`1 -methods: -- Foo(): T: - - +internal interface: RefasmerTestAssembly.IInterface2ToBeMarkedInternal`1 diff --git a/tests/Refasmer.Tests/data/IntegrationTests.InternalTypeInPublicApi_mainClassName=PublicClassWithInternalTypeInExplicitImpl.verified.txt b/tests/Refasmer.Tests/data/IntegrationTests.InternalTypeInPublicApi_mainClassName=PublicClassWithInternalTypeInExplicitImpl.verified.txt new file mode 100644 index 0000000..c65bcde --- /dev/null +++ b/tests/Refasmer.Tests/data/IntegrationTests.InternalTypeInPublicApi_mainClassName=PublicClassWithInternalTypeInExplicitImpl.verified.txt @@ -0,0 +1,5 @@ +public class: RefasmerTestAssembly.PublicClassWithInternalTypeInExplicitImpl + - interface impl: RefasmerTestAssembly.IInterface3 +methods: +- .ctor(): System.Void: +internal interface: RefasmerTestAssembly.IInterface3 diff --git a/tests/RefasmerTestAssembly/InternalClassInApi.cs b/tests/RefasmerTestAssembly/InternalTypesInApi.cs similarity index 70% rename from tests/RefasmerTestAssembly/InternalClassInApi.cs rename to tests/RefasmerTestAssembly/InternalTypesInApi.cs index 67e6d92..1e58399 100644 --- a/tests/RefasmerTestAssembly/InternalClassInApi.cs +++ b/tests/RefasmerTestAssembly/InternalTypesInApi.cs @@ -2,25 +2,36 @@ namespace RefasmerTestAssembly; -// Post-processed and converted to internal by tests: +// Types suffixed by "ToBeMarkedInternal" are post-processed and converted to internal by tests. public class Class1ToBeMarkedInternal; -public class Class2ToBeMarkedInternal; -public class Class3ToBeMarkedInternal; -public interface IInterface1ToBeMarkedInternal; -public interface IInterface2ToBeMarkedInternal -{ - T Foo(); -} public class PublicClassWithInternalTypeInApi { public void Accept(Class1ToBeMarkedInternal argument) {} } +public class Class2ToBeMarkedInternal; public class PublicClassDerivingFromInternal : Class2ToBeMarkedInternal; + +public interface IInterface1ToBeMarkedInternal; public class PublicClassImplementingInternal : IInterface1ToBeMarkedInternal; +public interface IInterface2ToBeMarkedInternal +{ + T Foo(); +} +public class Class3ToBeMarkedInternal; public class PublicClassWithInternalInterfaceImpl : IInterface2ToBeMarkedInternal { Class3ToBeMarkedInternal IInterface2ToBeMarkedInternal.Foo() => throw new Exception("123"); -} \ No newline at end of file +} + +internal class InternalClass3; +internal interface IInterface3 +{ + void Accept(InternalClass3 arg); +} +public class PublicClassWithInternalTypeInExplicitImpl : IInterface3 +{ + void IInterface3.Accept(InternalClass3 arg) {} +}