diff --git a/.github/workflows/IKVM.yml b/.github/workflows/IKVM.yml
index aefcff7cec..e0229fe73d 100644
--- a/.github/workflows/IKVM.yml
+++ b/.github/workflows/IKVM.yml
@@ -639,8 +639,8 @@ jobs:
"-v:diag",
"--results-directory", "TestResults",
"--logger:console;verbosity=diag",
- "--logger:trx",
- "--collect", "Code Coverage"
+ "--logger:trx"
+ # "--collect", "Code Coverage"
)
$runsettings = $(gi .\tests\$tst\$tfm\*.runsettings)
diff --git a/Directory.Build.targets b/Directory.Build.targets
index 23ab5af2fd..0c55181af6 100644
--- a/Directory.Build.targets
+++ b/Directory.Build.targets
@@ -2,4 +2,9 @@
+
+ win-x86
+ win-x64
+ true
+
diff --git a/README.md b/README.md
index c767b9ec6e..737e389f66 100644
--- a/README.md
+++ b/README.md
@@ -114,7 +114,7 @@ The output assembly will be generated as part of your project's build process an
MyClass.java;YourClass.java
SomeExternalDependency.jar;SomeOtherExternalDependency.jar
MyAssemblyAlias;helloworld2_0
- true
+ portable
```
@@ -139,7 +139,7 @@ The following values can be used as either an attribute or a nested element of `
| `Compile` | A semi-colon separated list of Java class path items to compile into the assembly. By default this value is the `Identity` of the item, if the identity of the item is an existing JAR file or directory (not yet supported). MSBuild globs are supported to reference multiple JAR or .class files. |
| `Sources` | A semi-colon separated list of Java source files to use during documentation generation. (not yet supported) |
| `References` | Optional semi-colon separated list of other `IkvmReference` identity values to specify as a reference to the current one. For example, if `foo.jar` depends on `bar.jar`, include both as `IkvmReference` items, but specify the identity of `bar.jar` on the `References` metadata of `foo.jar`. |
-| `Debug` | Optional boolean indicating whether to generate debug symbols. By default this is determined based on the `` and `` properties of the project. Only full debug symbols are currently supported. |
+| `Debug` | Optional value indicating how to generate debug symbols. By default this is determined based on the `` properties of the project. Only full debug symbols are currently supported. |
| `Aliases` | A semi-colon separated list of aliases that can be used to reference the assembly in `References`. |
| `ClassLoader` | A fully qualified classs name of the custom ClassLoader implementation to use as a delegation parent. Examples include `ikvm.runtime.AppDomainAssemblyClassLoader` and `ikvm.runtime.ClassPathAssemblyClassLoader`. |
| All other metadata supported on the [`Reference`](https://docs.microsoft.com/en-us/visualstudio/msbuild/common-msbuild-project-items#reference) MSBuild item group definition. | |
diff --git a/src/IKVM.ConsoleApp/IKVM.ConsoleApp.csproj b/src/IKVM.ConsoleApp/IKVM.ConsoleApp.csproj
index 81aca88366..37c5897649 100644
--- a/src/IKVM.ConsoleApp/IKVM.ConsoleApp.csproj
+++ b/src/IKVM.ConsoleApp/IKVM.ConsoleApp.csproj
@@ -1,7 +1,7 @@
Exe
- net481;net6.0
+ net6.0;net481;
11
x64
diff --git a/src/IKVM.ConsoleApp/Program.cs b/src/IKVM.ConsoleApp/Program.cs
index af3b03e04f..087f8ae107 100644
--- a/src/IKVM.ConsoleApp/Program.cs
+++ b/src/IKVM.ConsoleApp/Program.cs
@@ -1,4 +1,5 @@
using System;
+using System.Diagnostics;
namespace IKVM.ConsoleApp
{
@@ -13,7 +14,6 @@ public static void Main(string[] args)
public static void Foo()
{
new Bar();
- Environment.Exit(0);
}
class Bar
@@ -25,11 +25,6 @@ public Bar()
System.Console.WriteLine(java.net.InetAddress.getLocalHost().getHostName());
}
- ~Bar()
- {
-
- }
-
}
}
diff --git a/src/IKVM.Java.Tests/java/lang/ThreadTests.java b/src/IKVM.Java.Tests/java/lang/ThreadTests.java
new file mode 100644
index 0000000000..34cf4b712a
--- /dev/null
+++ b/src/IKVM.Java.Tests/java/lang/ThreadTests.java
@@ -0,0 +1,16 @@
+package ikvm.tests.java.java.lang;
+
+import java.lang.*;
+import java.util.*;
+
+@cli.Microsoft.VisualStudio.TestTools.UnitTesting.TestClassAttribute.Annotation()
+public class ThreadTests {
+
+ @cli.Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute.Annotation()
+ public void canPrintStackTrace() throws Throwable {
+ for (StackTraceElement ste : Thread.currentThread().getStackTrace()) {
+ System.out.println(ste + "\n");
+ }
+ }
+
+}
diff --git a/src/IKVM.Java/map.xml b/src/IKVM.Java/map.xml
index d72c5b7863..7e8081ad74 100644
--- a/src/IKVM.Java/map.xml
+++ b/src/IKVM.Java/map.xml
@@ -952,7 +952,8 @@
-
+
+
@@ -1010,7 +1011,7 @@
-
+
@@ -1019,7 +1020,7 @@
-
+
@@ -1341,18 +1342,29 @@
-
+
+
-
+
+
+
+
+
+
-
+
+
+
+
+
+
@@ -1398,14 +1410,21 @@
-
+
+
+
+
+
+
+
-
+
+
diff --git a/src/IKVM.MSBuild.Tasks/IkvmCompiler.cs b/src/IKVM.MSBuild.Tasks/IkvmCompiler.cs
index 1c84a19ea7..e4526d74a7 100644
--- a/src/IKVM.MSBuild.Tasks/IkvmCompiler.cs
+++ b/src/IKVM.MSBuild.Tasks/IkvmCompiler.cs
@@ -100,7 +100,7 @@ public class IkvmCompiler : IkvmToolExecTask
public bool CompressResources { get; set; }
- public bool Debug { get; set; }
+ public string Debug { get; set; }
public bool NoAutoSerialization { get; set; }
@@ -241,12 +241,6 @@ public override bool Execute()
protected override async Task ExecuteAsync(IkvmToolTaskDiagnosticWriter writer, CancellationToken cancellationToken)
{
- if (Debug && RuntimeInformation.IsOSPlatform(OSPlatform.Windows) == false)
- {
- Log.LogWarning("Emitting debug symbols from ikvmc is not supported on platforms other than Windows. Continuing without.");
- Debug = false;
- }
-
var options = new IkvmImporterOptions();
options.ResponseFile = ResponseFile;
options.Output = Output;
@@ -302,7 +296,16 @@ protected override async Task ExecuteAsync(IkvmToolTaskDiagnosticWriter wr
options.ExternalResources.Add(new IkvmImporterExternalResourceItem(resource.ItemSpec, resource.GetMetadata("ResourcePath")));
options.CompressResources = CompressResources;
- options.Debug = Debug;
+
+ options.Debug = Debug?.ToLower() switch
+ {
+ "none" or "" or null => IkvmImporterDebugMode.None,
+ "portable" => IkvmImporterDebugMode.Portable,
+ "full" or "pdbonly" => IkvmImporterDebugMode.Full,
+ "embedded" => IkvmImporterDebugMode.Embedded,
+ _ => throw new NotImplementedException($"Unknown Debug option '{Debug}'.")
+ };
+
options.NoAutoSerialization = NoAutoSerialization;
options.NoGlobbing = NoGlobbing;
options.NoJNI = NoJNI;
diff --git a/src/IKVM.MSBuild.Tasks/IkvmReferenceItem.cs b/src/IKVM.MSBuild.Tasks/IkvmReferenceItem.cs
index cddd1c597d..f1e900a330 100644
--- a/src/IKVM.MSBuild.Tasks/IkvmReferenceItem.cs
+++ b/src/IKVM.MSBuild.Tasks/IkvmReferenceItem.cs
@@ -62,7 +62,7 @@ public static IkvmReferenceItem[] Import(IEnumerable items)
item.References = ResolveReferences(map, item, item.Item.GetMetadata(IkvmReferenceItemMetadata.References)).ToList();
item.ClassLoader = item.Item.GetMetadata(IkvmReferenceItemMetadata.ClassLoader);
item.ResolvedReferences = item.Item.GetMetadata(IkvmReferenceItemMetadata.ResolvedReferences)?.Split(IkvmReferenceItemMetadata.PropertySeperatorCharArray, StringSplitOptions.RemoveEmptyEntries).ToList();
- item.Debug = string.Equals(item.Item.GetMetadata(IkvmReferenceItemMetadata.Debug), "true", StringComparison.OrdinalIgnoreCase);
+ item.Debug = ParseDebug(item.Item.GetMetadata(IkvmReferenceItemMetadata.Debug));
item.KeyFile = item.Item.GetMetadata(IkvmReferenceItemMetadata.KeyFile);
item.DelaySign = string.Equals(item.Item.GetMetadata(IkvmReferenceItemMetadata.DelaySign), "true", StringComparison.OrdinalIgnoreCase);
item.Aliases = item.Item.GetMetadata(IkvmReferenceItemMetadata.Aliases);
@@ -79,6 +79,21 @@ public static IkvmReferenceItem[] Import(IEnumerable items)
return map.Values.ToArray();
}
+ ///
+ /// Parses the debug metadata value into the enum.
+ ///
+ ///
+ ///
+ ///
+ static IkvmReferenceItemDebug ParseDebug(string debug) => debug?.ToLower() switch
+ {
+ "none" or "false" or "" or null => IkvmReferenceItemDebug.None,
+ "full" or "true" => IkvmReferenceItemDebug.Full,
+ "portable" => IkvmReferenceItemDebug.Portable,
+ "embedded" => IkvmReferenceItemDebug.Embedded,
+ _ => IkvmReferenceItemDebug.None
+ };
+
///
/// Attempts to resolve the references given by the reference string for
/// against .
@@ -229,7 +244,7 @@ public IkvmReferenceItem(ITaskItem item)
///
/// Compile in debug mode.
///
- public bool Debug { get; set; }
+ public IkvmReferenceItemDebug Debug { get; set; }
///
/// Path to the file to sign the assembly.
@@ -279,7 +294,7 @@ public void Save()
Item.SetMetadata(IkvmReferenceItemMetadata.StagePath, StagePath);
Item.SetMetadata(IkvmReferenceItemMetadata.StageSymbolsPath, StageSymbolsPath);
Item.SetMetadata(IkvmReferenceItemMetadata.Aliases, Aliases);
- Item.SetMetadata(IkvmReferenceItemMetadata.Debug, Debug ? "true" : "false");
+ Item.SetMetadata(IkvmReferenceItemMetadata.Debug, ToString(Debug));
Item.SetMetadata(IkvmReferenceItemMetadata.KeyFile, KeyFile);
Item.SetMetadata(IkvmReferenceItemMetadata.DelaySign, DelaySign ? "true" : "false");
Item.SetMetadata(IkvmReferenceItemMetadata.Private, Private ? "true" : "false");
@@ -287,6 +302,21 @@ public void Save()
Item.SetMetadata(IkvmReferenceItemMetadata.ResolvedReferences, string.Join(IkvmReferenceItemMetadata.PropertySeperatorString, ResolvedReferences));
}
+ ///
+ /// Converts the enum value to a string.
+ ///
+ ///
+ ///
+ ///
+ string ToString(IkvmReferenceItemDebug debug) => debug switch
+ {
+ IkvmReferenceItemDebug.None => "none",
+ IkvmReferenceItemDebug.Full => "full",
+ IkvmReferenceItemDebug.Portable => "portable",
+ IkvmReferenceItemDebug.Embedded => "embedded",
+ _ => throw new NotImplementedException(),
+ };
+
}
}
diff --git a/src/IKVM.MSBuild.Tasks/IkvmReferenceItemDebug.cs b/src/IKVM.MSBuild.Tasks/IkvmReferenceItemDebug.cs
new file mode 100644
index 0000000000..17ccf71863
--- /dev/null
+++ b/src/IKVM.MSBuild.Tasks/IkvmReferenceItemDebug.cs
@@ -0,0 +1,14 @@
+namespace IKVM.MSBuild.Tasks
+{
+
+ enum IkvmReferenceItemDebug
+ {
+
+ None,
+ Full,
+ Portable,
+ Embedded,
+
+ }
+
+}
\ No newline at end of file
diff --git a/src/IKVM.MSBuild.Tasks/IkvmReferenceItemPrepare.cs b/src/IKVM.MSBuild.Tasks/IkvmReferenceItemPrepare.cs
index 2fedec3e22..f7e3063781 100644
--- a/src/IKVM.MSBuild.Tasks/IkvmReferenceItemPrepare.cs
+++ b/src/IKVM.MSBuild.Tasks/IkvmReferenceItemPrepare.cs
@@ -500,7 +500,7 @@ internal async Task CalculateIkvmIdentityAsync(IkvmReferenceItem item, C
manifest.WriteLine("AssemblyVersion={0}", item.AssemblyVersion);
manifest.WriteLine("AssemblyFileVersion={0}", item.AssemblyFileVersion);
manifest.WriteLine("ClassLoader={0}", item.ClassLoader);
- manifest.WriteLine("Debug={0}", item.Debug ? "true" : "false");
+ manifest.WriteLine("Debug={0}", Enum.GetName(typeof(IkvmReferenceItemDebug), item.Debug));
manifest.WriteLine("KeyFile={0}", string.IsNullOrWhiteSpace(item.KeyFile) == false ? await fileIdentityUtil.GetIdentityForFileAsync(item.KeyFile, Log, cancellationToken) : "");
manifest.WriteLine("DelaySign={0}", item.DelaySign ? "true" : "false");
diff --git a/src/IKVM.MSBuild.Tests/IKVM.MSBuild.Tests.csproj b/src/IKVM.MSBuild.Tests/IKVM.MSBuild.Tests.csproj
index 9ac8a1ed1c..5bd05d0dbd 100644
--- a/src/IKVM.MSBuild.Tests/IKVM.MSBuild.Tests.csproj
+++ b/src/IKVM.MSBuild.Tests/IKVM.MSBuild.Tests.csproj
@@ -22,7 +22,7 @@
-
+
diff --git a/src/IKVM.MSBuild.Tests/Project/global.json b/src/IKVM.MSBuild.Tests/Project/global.json
index 912bc7602d..857e6681f3 100644
--- a/src/IKVM.MSBuild.Tests/Project/global.json
+++ b/src/IKVM.MSBuild.Tests/Project/global.json
@@ -1,6 +1,6 @@
{
"sdk": {
- "version": "7.0.0",
+ "version": "7.0.100",
"rollForward": "latestFeature"
}
}
diff --git a/src/IKVM.MSBuild.Tests/ProjectTests.cs b/src/IKVM.MSBuild.Tests/ProjectTests.cs
index f1cd5cac4b..de88fb3c90 100644
--- a/src/IKVM.MSBuild.Tests/ProjectTests.cs
+++ b/src/IKVM.MSBuild.Tests/ProjectTests.cs
@@ -54,6 +54,8 @@ void OnAnyEventRaised(object sender, BuildEventArgs args)
public static Dictionary Properties { get; set; }
+ public static string TestRoot { get; set; }
+
public static string TempRoot { get; set; }
public static string WorkRoot { get; set; }
@@ -70,6 +72,9 @@ public static void ClassInitialize(TestContext context)
// properties to load into test build
Properties = File.ReadAllLines("IKVM.MSBuild.Tests.properties").Select(i => i.Split('=', 2)).ToDictionary(i => i[0], i => i[1]);
+ // root of the project collection itself
+ TestRoot = Path.Combine(Path.GetDirectoryName(typeof(ProjectTests).Assembly.Location), "Project");
+
// temporary directory
TempRoot = Path.Combine(Path.GetTempPath(), "IKVM.MSBuild.Tests", Guid.NewGuid().ToString());
if (Directory.Exists(TempRoot))
@@ -102,10 +107,10 @@ public static void ClassInitialize(TestContext context)
new XElement("add",
new XAttribute("key", "dev"),
new XAttribute("value", Path.Combine(Path.GetDirectoryName(typeof(ProjectTests).Assembly.Location), @"nuget"))))))
- .Save(Path.Combine(@"Project", "nuget.config"));
+ .Save(Path.Combine(TestRoot, "nuget.config"));
var manager = new AnalyzerManager();
- var analyzer = manager.GetProject(Path.Combine(@"Project", "Exe", "ProjectExe.csproj"));
+ var analyzer = manager.GetProject(Path.Combine(TestRoot, "Exe", "ProjectExe.csproj"));
analyzer.AddBuildLogger(new TargetLogger(context));
analyzer.AddBinaryLogger(Path.Combine(WorkRoot, "msbuild.binlog"));
analyzer.SetGlobalProperty("ImportDirectoryBuildProps", "false");
@@ -122,6 +127,7 @@ public static void ClassInitialize(TestContext context)
analyzer.SetGlobalProperty("Configuration", "Release");
var options = new EnvironmentOptions();
+ options.WorkingDirectory = TestRoot;
options.DesignTime = false;
options.Restore = true;
options.TargetsToBuild.Clear();
@@ -205,7 +211,7 @@ public void CanBuildTestProject(EnvironmentPreference env, string tfm, string ri
return;
var manager = new AnalyzerManager();
- var analyzer = manager.GetProject(Path.Combine("Project", "Exe", "ProjectExe.csproj"));
+ var analyzer = manager.GetProject(Path.Combine(TestRoot, "Exe", "ProjectExe.csproj"));
analyzer.AddBuildLogger(new TargetLogger(TestContext));
analyzer.AddBinaryLogger(Path.Combine(WorkRoot, $"{tfm}-{rid}-msbuild.binlog"));
analyzer.SetGlobalProperty("ImportDirectoryBuildProps", "false");
@@ -222,6 +228,7 @@ public void CanBuildTestProject(EnvironmentPreference env, string tfm, string ri
analyzer.SetGlobalProperty("Configuration", "Release");
var options = new EnvironmentOptions();
+ options.WorkingDirectory = TestRoot;
options.Preference = env;
options.DesignTime = false;
options.Restore = false;
diff --git a/src/IKVM.NET.Sdk.Tests/IKVM.NET.Sdk.Tests.csproj b/src/IKVM.NET.Sdk.Tests/IKVM.NET.Sdk.Tests.csproj
index 4b5dec7700..d0f8d5e694 100644
--- a/src/IKVM.NET.Sdk.Tests/IKVM.NET.Sdk.Tests.csproj
+++ b/src/IKVM.NET.Sdk.Tests/IKVM.NET.Sdk.Tests.csproj
@@ -12,7 +12,7 @@
-
+
diff --git a/src/IKVM.NET.Sdk.Tests/ProjectTests.cs b/src/IKVM.NET.Sdk.Tests/ProjectTests.cs
index e9e9e5db54..02af1a9de0 100644
--- a/src/IKVM.NET.Sdk.Tests/ProjectTests.cs
+++ b/src/IKVM.NET.Sdk.Tests/ProjectTests.cs
@@ -48,6 +48,8 @@ public override void Initialize(IEventSource eventSource)
public static Dictionary Properties { get; set; }
+ public static string TestRoot { get; set; }
+
public static string TempRoot { get; set; }
public static string WorkRoot { get; set; }
@@ -64,6 +66,9 @@ public static void Init(TestContext context)
// properties to load into test build
Properties = File.ReadAllLines("IKVM.NET.Sdk.Tests.properties").Select(i => i.Split('=', 2)).ToDictionary(i => i[0], i => i[1]);
+ // root of the project collection itself
+ TestRoot = Path.Combine(Path.GetDirectoryName(typeof(ProjectTests).Assembly.Location), "Project");
+
// temporary directory
TempRoot = Path.Combine(Path.GetTempPath(), "IKVM.NET.Sdk.Tests", Guid.NewGuid().ToString());
if (Directory.Exists(TempRoot))
@@ -96,10 +101,10 @@ public static void Init(TestContext context)
new XElement("add",
new XAttribute("key", "dev"),
new XAttribute("value", Path.Combine(Path.GetDirectoryName(typeof(ProjectTests).Assembly.Location), @"nuget"))))))
- .Save(Path.Combine(@"Project", "nuget.config"));
+ .Save(Path.Combine(TestRoot, "nuget.config"));
var manager = new AnalyzerManager();
- var analyzer = manager.GetProject(Path.Combine(@"Project", "Exe", "ProjectExe.msbuildproj"));
+ var analyzer = manager.GetProject(Path.Combine(TestRoot, "Exe", "ProjectExe.msbuildproj"));
analyzer.AddBuildLogger(new TargetLogger(context));
analyzer.AddBinaryLogger(Path.Combine(WorkRoot, "msbuild.binlog"));
analyzer.SetGlobalProperty("ImportDirectoryBuildProps", "false");
@@ -116,6 +121,7 @@ public static void Init(TestContext context)
analyzer.SetGlobalProperty("Configuration", "Release");
var options = new EnvironmentOptions();
+ options.WorkingDirectory = TestRoot;
options.DesignTime = false;
options.Restore = true;
options.TargetsToBuild.Clear();
@@ -213,6 +219,7 @@ public void CanBuildTestProject(EnvironmentPreference env, string tfm, string ri
analyzer.SetGlobalProperty("Configuration", "Release");
var options = new EnvironmentOptions();
+ options.WorkingDirectory = TestRoot;
options.Preference = env;
options.DesignTime = false;
options.Restore = false;
diff --git a/src/IKVM.NET.Sdk/targets/IKVM.Java.Core.NoTasks.targets b/src/IKVM.NET.Sdk/targets/IKVM.Java.Core.NoTasks.targets
index 77f4914d54..713fbd42c7 100644
--- a/src/IKVM.NET.Sdk/targets/IKVM.Java.Core.NoTasks.targets
+++ b/src/IKVM.NET.Sdk/targets/IKVM.Java.Core.NoTasks.targets
@@ -235,7 +235,7 @@ Items = Items.OrderBy(i => i.ItemSpec).ToArray();
<_IkvmCompilerArgs Remove="@(_IkvmCompilerArgs)" />
<_IkvmCompilerArgs Include="-nologo" />
<_IkvmCompilerArgs Include="-bootstrap" Condition=" '$(Bootstrap)' == 'true' " />
- <_IkvmCompilerArgs Include="-debug" Condition=" '$(DebugSymbols)' == 'true' Or '$(DebugType)' != 'none' " />
+ <_IkvmCompilerArgs Include="-debug:$(DebugType)" Condition=" '$(DebugType)' != 'none' " />
<_IkvmCompilerArgs Include="-assembly:$(AssemblyName)" />
<_IkvmCompilerArgs Include="-version:$(AssemblyVersion)" />
<_IkvmCompilerArgs Include="-runtime:$(IkvmRuntimeAssembly)" />
diff --git a/src/IKVM.NET.Sdk/targets/IKVM.Java.Core.Tasks.targets b/src/IKVM.NET.Sdk/targets/IKVM.Java.Core.Tasks.targets
index 99bf6d6c95..5eb16bc672 100644
--- a/src/IKVM.NET.Sdk/targets/IKVM.Java.Core.Tasks.targets
+++ b/src/IKVM.NET.Sdk/targets/IKVM.Java.Core.Tasks.targets
@@ -57,7 +57,7 @@
<_JavaCompilerDebug Condition=" '$(DebugSymbols)' == 'true' Or '$(DebugType)' != 'none' ">all
-
+
- <_IkvmCompilerDebug Condition=" '$(DebugType)' != 'none' ">true
<_IkvmCompilerExclude Condition="Exists('$(_ExcludeFilePath)')">$(_ExcludeFilePath)
<_Target>$(OutputType.ToLowerInvariant())
<_Target Condition="$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'netcoreapp3.1'))">library
@@ -128,7 +127,7 @@
Target="$(_Target)"
Platform="$(PlatformTarget.ToLowerInvariant())"
Main="$(StartupObject)"
- Debug="$(_IkvmCompilerDebug)"
+ Debug="$(DebugType)"
KeyFile="$(KeyOriginatorFile)"
CompressResources="$(CompressResources)"
ClassLoader="$(ClassLoader)"
diff --git a/src/IKVM.NET.Sdk/targets/IKVM.NET.Sdk.props b/src/IKVM.NET.Sdk/targets/IKVM.NET.Sdk.props
index 641086a101..e007dcb58a 100644
--- a/src/IKVM.NET.Sdk/targets/IKVM.NET.Sdk.props
+++ b/src/IKVM.NET.Sdk/targets/IKVM.NET.Sdk.props
@@ -26,7 +26,6 @@
true
true
true
- false
diff --git a/src/IKVM.Reflection.Tests/ModuleWriterTests.cs b/src/IKVM.Reflection.Tests/ModuleWriterTests.cs
index 73fd94e611..64f7f0e7d5 100644
--- a/src/IKVM.Reflection.Tests/ModuleWriterTests.cs
+++ b/src/IKVM.Reflection.Tests/ModuleWriterTests.cs
@@ -1,8 +1,12 @@
using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
using System.IO;
using System.Reflection;
+using System.Reflection.Metadata;
using System.Reflection.PortableExecutable;
using System.Runtime.InteropServices;
+using System.Text;
using FluentAssertions;
@@ -25,6 +29,7 @@ class VerifyResolver : ILVerify.IResolver
{
readonly TestAssemblyResolver resolver;
+ readonly ConcurrentDictionary cache = new ConcurrentDictionary();
///
/// Initializes a new instance.
@@ -37,7 +42,7 @@ public VerifyResolver(TestAssemblyResolver resolver)
public PEReader ResolveAssembly(System.Reflection.AssemblyName assemblyName)
{
- return resolver.Resolve(assemblyName.Name) is string s ? new PEReader(File.OpenRead(s)) : null;
+ return cache.GetOrAdd(assemblyName.Name, _ => resolver.Resolve(_) is string s ? new PEReader(File.OpenRead(s)) : null);
}
public PEReader ResolveModule(System.Reflection.AssemblyName referencingAssembly, string fileName)
@@ -88,7 +93,22 @@ public ModuleWriterTests(ITestOutputHelper output)
///
///
///
+ ///
bool Init(FrameworkSpec framework, out Universe universe, out TestAssemblyResolver resolver, out ILVerify.Verifier verifier, out string tempPath, out MetadataLoadContext tempLoad)
+ {
+ return Init(framework, null, out universe, out resolver, out verifier, out tempPath, out tempLoad);
+ }
+
+ ///
+ /// Initializes the variables requires to execute tests.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ bool Init(FrameworkSpec framework, IEnumerable searchPaths, out Universe universe, out TestAssemblyResolver resolver, out ILVerify.Verifier verifier, out string tempPath, out MetadataLoadContext tempLoad)
{
universe = null;
resolver = null;
@@ -110,8 +130,8 @@ bool Init(FrameworkSpec framework, out Universe universe, out TestAssemblyResolv
// initialize primary classes
universe = new Universe(DotNetSdkUtil.GetCoreLibName(framework.Tfm, framework.TargetFrameworkIdentifier, framework.TargetFrameworkVersion));
- resolver = new TestAssemblyResolver(universe, framework.Tfm, framework.TargetFrameworkIdentifier, framework.TargetFrameworkVersion);
- verifier = new ILVerify.Verifier(new VerifyResolver(resolver), new ILVerify.VerifierOptions() { SanityChecks = true });
+ resolver = new TestAssemblyResolver(universe, framework.Tfm, framework.TargetFrameworkIdentifier, framework.TargetFrameworkVersion, searchPaths);
+ verifier = new ILVerify.Verifier(new VerifyResolver(resolver), new ILVerify.VerifierOptions() { IncludeMetadataTokensInErrorMessages = true, SanityChecks = true });
verifier.SetSystemModuleName(new System.Reflection.AssemblyName(universe.CoreLibName));
tempLoad = new MetadataLoadContext(new MetadataAssemblyResolver(resolver));
@@ -464,6 +484,79 @@ public void CanWriteWindowsApplication(FrameworkSpec framework)
t.Should().HaveMethod("Main", new[] { tempLoad.CoreAssembly.GetType("System.String").MakeArrayType() }).Which.Should().Return(tempLoad.CoreAssembly.GetType("System.Void"));
}
+ [Theory]
+ [MemberData(nameof(FrameworkSpec.GetFrameworkTestData), MemberType = typeof(FrameworkSpec))]
+ public void CanWriteTryCatch(FrameworkSpec framework)
+ {
+ if (Init(framework, out var universe, out var resolver, out var verifier, out var tempPath, out var tempLoad) == false)
+ return;
+
+ var assembly = universe.DefineDynamicAssembly(new AssemblyName("Test"), AssemblyBuilderAccess.Save, tempPath);
+ var module = assembly.DefineDynamicModule("Test", "Test.dll", false);
+ var type = module.DefineType("Type");
+
+ var execMethod = type.DefineMethod("Exec", MethodAttributes.Public, null, Array.Empty());
+ var execMethodIL = execMethod.GetILGenerator();
+
+ var end = execMethodIL.BeginExceptionBlock();
+ execMethodIL.Emit(OpCodes.Nop);
+ execMethodIL.BeginCatchBlock(universe.Import(typeof(Exception)));
+ execMethodIL.Emit(OpCodes.Nop);
+ execMethodIL.EndExceptionBlock();
+ execMethodIL.Emit(OpCodes.Ret);
+
+ type.CreateType();
+ assembly.Save("Test.dll");
+
+ foreach (var v in verifier.Verify(new PEReader(File.OpenRead(Path.Combine(tempPath, "Test.dll")))))
+ if (v.Code != ILVerify.VerifierError.None)
+ throw new Exception(string.Format(v.Message, v.Args ?? Array.Empty