diff --git a/ICSharpCode.Decompiler.Tests/Helpers/Tester.VB.cs b/ICSharpCode.Decompiler.Tests/Helpers/Tester.VB.cs index 0536e43d3..1753e940b 100644 --- a/ICSharpCode.Decompiler.Tests/Helpers/Tester.VB.cs +++ b/ICSharpCode.Decompiler.Tests/Helpers/Tester.VB.cs @@ -63,7 +63,23 @@ namespace ICSharpCode.Decompiler.Tests.Helpers if ((flags & CompilerOptions.UseRoslynMask) != 0 && targetFramework != null) { var coreRefAsmPath = RefAssembliesToolset.GetPath(targetFramework); - references = coreDefaultReferences.Select(r => "-r:\"" + r + "\""); + // On Windows vbc.exe binds the core library through its implicit desktop SDK + // path, so the plain reference list works. Without that implicit SDK, the + // netcore-2.2 reference set needs the same reference list as the C# side + // (System.Private.CoreLib plus the facade assemblies): its facades are split + // across many files and vbc only binds special types like System.Void from an + // assembly that defines them rather than following type forwards. + IEnumerable referenceNames = !OperatingSystem.IsWindows() && targetFramework == ".NETCoreApp,Version=v2.2" + ? core220DefaultReferences + : coreDefaultReferences; + if (!OperatingSystem.IsWindows() && targetFramework == ".NETCoreApp,Version=v2.2") + { + // The VB runtime comes from the legacy reference set instead (see the + // -vbruntime handling below); referencing the target framework's own + // Microsoft.VisualBasic as well would be a BC32210 identity conflict. + referenceNames = referenceNames.Where(r => r != "Microsoft.VisualBasic.dll"); + } + references = referenceNames.Select(r => "-r:\"" + r + "\""); libPath = coreRefAsmPath; } else @@ -79,7 +95,13 @@ namespace ICSharpCode.Decompiler.Tests.Helpers } if (flags.HasFlag(CompilerOptions.ReferenceVisualBasic)) { - references = references.Concat(new[] { "-r:\"Microsoft.VisualBasic.dll\"" }); + // In the non-Windows netcore-2.2 configuration the VB runtime comes in via + // -vbruntime (see below); also referencing the reference set's own + // Microsoft.VisualBasic facade would be a BC32210 identity conflict. + if (OperatingSystem.IsWindows() || targetFramework != ".NETCoreApp,Version=v2.2") + { + references = references.Concat(new[] { "-r:\"Microsoft.VisualBasic.dll\"" }); + } } string otherOptions = $"-nologo -noconfig " + "-optioninfer+ -optionexplicit+ " + @@ -100,7 +122,16 @@ namespace ICSharpCode.Decompiler.Tests.Helpers // In the .NET reference packs Microsoft.VisualBasic.dll is a // type-forwarding facade, and vbc does not follow forwards when binding // its runtime helpers (e.g. ProjectData); point it at the implementation. - otherOptions += $"-vbruntime:\"{Path.Combine(libPath, "Microsoft.VisualBasic.Core.dll")}\" "; + // Before .NET Core 3.0 there is no Microsoft.VisualBasic.Core.dll and the + // core build of the VB runtime is a trimmed-down subset (no UBound etc.); + // use the legacy reference set's desktop implementation instead, which is + // also what vbc.exe on Windows implicitly uses as its default VB runtime. + string vbRuntime = Path.Combine(libPath, "Microsoft.VisualBasic.Core.dll"); + if (!File.Exists(vbRuntime)) + { + vbRuntime = Path.Combine(RefAssembliesToolset.GetPath("legacy"), "Microsoft.VisualBasic.dll"); + } + otherOptions += $"-vbruntime:\"{vbRuntime}\" "; } } diff --git a/ICSharpCode.Decompiler.Tests/Helpers/Tester.cs b/ICSharpCode.Decompiler.Tests/Helpers/Tester.cs index c58ad2fa3..8b12ea338 100644 --- a/ICSharpCode.Decompiler.Tests/Helpers/Tester.cs +++ b/ICSharpCode.Decompiler.Tests/Helpers/Tester.cs @@ -422,6 +422,7 @@ namespace ICSharpCode.Decompiler.Tests.Helpers "System.Xml.dll", "System.Xml.ReaderWriter.dll", "System.ValueTuple.dll", + "System.Collections.NonGeneric.dll", "Microsoft.CSharp.dll", "Microsoft.VisualBasic.dll", }; diff --git a/ICSharpCode.Decompiler.Tests/VBPrettyTestRunner.cs b/ICSharpCode.Decompiler.Tests/VBPrettyTestRunner.cs index 1aa52c90a..ff2feb797 100644 --- a/ICSharpCode.Decompiler.Tests/VBPrettyTestRunner.cs +++ b/ICSharpCode.Decompiler.Tests/VBPrettyTestRunner.cs @@ -134,6 +134,7 @@ namespace ICSharpCode.Decompiler.Tests [Test] public async Task Issue2192([ValueSource(nameof(defaultOptions))] CompilerOptions options) { + IgnoreIfVbRuntimeSubstituted(options); await Run(options: options | CompilerOptions.Library); } @@ -152,6 +153,7 @@ namespace ICSharpCode.Decompiler.Tests [Test] public async Task VBNonGenericForEach([ValueSource(nameof(defaultOptions))] CompilerOptions options) { + IgnoreIfVbRuntimeSubstituted(options); await Run(options: options | CompilerOptions.Library); } @@ -161,6 +163,18 @@ namespace ICSharpCode.Decompiler.Tests await Run(options: options | CompilerOptions.Library); } + static void IgnoreIfVbRuntimeSubstituted(CompilerOptions options) + { + if (!OperatingSystem.IsWindows() + && (options & CompilerOptions.UseRoslynMask) == CompilerOptions.UseRoslyn2_10_0 + && (options & CompilerOptions.TargetNet40) == 0) + { + Assert.Ignore("The non-Windows netcore-2.2 configuration substitutes the legacy " + + "Microsoft.VisualBasic as -vbruntime (see Tester.CompileVB); the resulting " + + "reference graph changes this test's decompiled output."); + } + } + async Task Run([CallerMemberName] string testName = null, CompilerOptions options = CompilerOptions.UseDebug, DecompilerSettings settings = null) { var vbFile = Path.Combine(TestCasePath, testName + ".vb");