diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index 1d7971b..139cf26 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -29,7 +29,7 @@ jobs: run: dotnet pack -p:PackageOutputPath="${GITHUB_WORKSPACE}/packages" -p:IncludeSymbols=false -p:RepositoryCommit=${GITHUB_SHA} -p:PackageVersion="0.0.0.1" - name: Test - run: dotnet test --no-build --verbosity normal + run: dotnet test --framework net8.0 --no-build --verbosity normal - name: Upload Binary Log uses: actions/upload-artifact@v3 diff --git a/Src/Basic.Reference.Assemblies.Net461/Basic.Reference.Assemblies.Net461.csproj b/Src/Basic.Reference.Assemblies.Net461/Basic.Reference.Assemblies.Net461.csproj index 9ef9ece..e0386b9 100644 --- a/Src/Basic.Reference.Assemblies.Net461/Basic.Reference.Assemblies.Net461.csproj +++ b/Src/Basic.Reference.Assemblies.Net461/Basic.Reference.Assemblies.Net461.csproj @@ -8,6 +8,7 @@ + diff --git a/Src/Basic.Reference.Assemblies.Net461/Generated.cs b/Src/Basic.Reference.Assemblies.Net461/Generated.cs index 8668cb1..323197c 100644 --- a/Src/Basic.Reference.Assemblies.Net461/Generated.cs +++ b/Src/Basic.Reference.Assemblies.Net461/Generated.cs @@ -4476,6 +4476,11 @@ public static class ExtraReferenceInfos /// The for System.Threading.Tasks.Extensions.dll /// public static ReferenceInfo SystemThreadingTasksExtensions => new ReferenceInfo("System.Threading.Tasks.Extensions.dll", Resources.SystemThreadingTasksExtensions, Net461.ExtraReferences.SystemThreadingTasksExtensions, global::System.Guid.Parse("bc890e4e-a34f-463c-8fd9-60f43c8beb88")); + + /// + /// The for System.ValueTuple.dll + /// + public static ReferenceInfo SystemValueTuple => new ReferenceInfo("System.ValueTuple.dll", Resources.SystemValueTuple, Net461.ExtraReferences.SystemValueTuple, global::System.Guid.Parse("1aa5ee86-d143-43bd-94ec-c0749ff98222")); private static ImmutableArray _all; public static ImmutableArray All { @@ -4486,6 +4491,7 @@ public static ImmutableArray All _all = [ SystemThreadingTasksExtensions, + SystemValueTuple, ]; } return _all; @@ -4517,6 +4523,23 @@ public static PortableExecutableReference SystemThreadingTasksExtensions } } + private static PortableExecutableReference? _SystemValueTuple; + + /// + /// The for System.ValueTuple.dll + /// + public static PortableExecutableReference SystemValueTuple + { + get + { + if (_SystemValueTuple is null) + { + _SystemValueTuple = AssemblyMetadata.CreateFromImage(Resources.SystemValueTuple).GetReference(filePath: "System.ValueTuple.dll", display: "System.ValueTuple (net461)"); + } + return _SystemValueTuple; + } + } + private static ImmutableArray _all; public static ImmutableArray All { @@ -4527,6 +4550,7 @@ public static ImmutableArray All _all = [ SystemThreadingTasksExtensions, + SystemValueTuple, ]; } return _all; @@ -5649,6 +5673,12 @@ public static class Resources public static byte[] SystemThreadingTasksExtensions => ResourceLoader.GetOrCreateResource(ref _SystemThreadingTasksExtensions, "net461.System.Threading.Tasks.Extensions"); private static byte[]? _SystemThreadingTasksExtensions; + /// + /// The image bytes for System.ValueTuple.dll + /// + public static byte[] SystemValueTuple => ResourceLoader.GetOrCreateResource(ref _SystemValueTuple, "net461.System.ValueTuple"); + private static byte[]? _SystemValueTuple; + } } diff --git a/Src/Basic.Reference.Assemblies.Net461/Generated.targets b/Src/Basic.Reference.Assemblies.Net461/Generated.targets index 40fd5f5..ef17a87 100644 --- a/Src/Basic.Reference.Assemblies.Net461/Generated.targets +++ b/Src/Basic.Reference.Assemblies.Net461/Generated.targets @@ -740,5 +740,9 @@ net461.System.Threading.Tasks.Extensions Resources\net461\System.Threading.Tasks.Extensions.dll + + net461.System.ValueTuple + Resources\net461\System.ValueTuple.dll + diff --git a/Src/Basic.Reference.Assemblies.UnitTests/Basic.Reference.Assemblies.UnitTests.csproj b/Src/Basic.Reference.Assemblies.UnitTests/Basic.Reference.Assemblies.UnitTests.csproj index 47b5d0f..1d88aa5 100644 --- a/Src/Basic.Reference.Assemblies.UnitTests/Basic.Reference.Assemblies.UnitTests.csproj +++ b/Src/Basic.Reference.Assemblies.UnitTests/Basic.Reference.Assemblies.UnitTests.csproj @@ -1,7 +1,7 @@  - net8.0 + net8.0;net472 false LatestMajor diff --git a/Src/Basic.Reference.Assemblies.UnitTests/CompilationUtil.cs b/Src/Basic.Reference.Assemblies.UnitTests/CompilationUtil.cs new file mode 100644 index 0000000..79be56c --- /dev/null +++ b/Src/Basic.Reference.Assemblies.UnitTests/CompilationUtil.cs @@ -0,0 +1,77 @@ +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.Operations; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace Basic.Reference.Assemblies.UnitTests; +internal static class CompilationUtil +{ + public static MemoryStream CompileToLibrary(string code, string assemblyName, IEnumerable references) + { + var options = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary); + var compilation = CSharpCompilation.Create( + assemblyName, + [CSharpSyntaxTree.ParseText(code)], + references, + options); + + var peStream = new MemoryStream(); + var emitResult = compilation.Emit(peStream); + if (!emitResult.Success) + { + throw new Exception(GetMessage(emitResult.Diagnostics)); + } + + peStream.Position = 0; + return peStream; + + static string GetMessage(IEnumerable diagnostics) + { + var builder = new StringBuilder(); + builder.AppendLine("Compilation failed with the following errors:"); + foreach (var d in diagnostics) + { + builder.AppendLine(d.ToString()); + } + return builder.ToString(); + } + } + + public static Assembly CompileToLibraryAndLoad(string code, string assemblyName, IEnumerable references) + { + var stream = CompileToLibrary(code, assemblyName, references); + return Load(stream, assemblyName); + } + + /// + /// Compile and run the code expecting to find a static Lib.Go method + /// + public static string? CompileAndRun(string code, string assemblyName, IEnumerable references) + { + var assembly = CompileToLibraryAndLoad(code, assemblyName, references); + var libType = assembly + .GetTypes() + .Where(x => x.Name == "Lib") + .Single(); + var method = libType.GetMethod("Go", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public); + var obj = method!.Invoke(null, null); + return (string?)obj; + } + + public static Assembly Load(MemoryStream stream, string assemblyName) + { + stream.Position = 0; +#if NET + var alc = new System.Runtime.Loader.AssemblyLoadContext(assemblyName); + return alc.LoadFromStream(stream); +#else + return Assembly.Load(stream.ToArray()); +#endif + } +} diff --git a/Src/Basic.Reference.Assemblies.UnitTests/Extensions.cs b/Src/Basic.Reference.Assemblies.UnitTests/Extensions.cs index dd5861a..e4f8518 100644 --- a/Src/Basic.Reference.Assemblies.UnitTests/Extensions.cs +++ b/Src/Basic.Reference.Assemblies.UnitTests/Extensions.cs @@ -1,7 +1,10 @@ using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; using System; using System.Collections.Generic; +using System.IO; using System.Linq; +using System.Reflection; using System.Text; using System.Threading.Tasks; diff --git a/Src/Basic.Reference.Assemblies.UnitTests/SanityUnitTests.cs b/Src/Basic.Reference.Assemblies.UnitTests/SanityUnitTests.cs index ea551b2..438644c 100644 --- a/Src/Basic.Reference.Assemblies.UnitTests/SanityUnitTests.cs +++ b/Src/Basic.Reference.Assemblies.UnitTests/SanityUnitTests.cs @@ -13,6 +13,12 @@ namespace Basic.Reference.Assemblies.UnitTests; public class SanityUnitTests(ITestOutputHelper outputHelper) { public ITestOutputHelper TestOutputHelper { get; } = outputHelper; + public bool IsCoreClr => +#if NET + true; +#else + false; +#endif [Theory] [MemberData(nameof(TestData.ApplicationReferences), MemberType = typeof(TestData))] @@ -176,4 +182,25 @@ static void Main() Assert.True(emitResult.Success); Assert.Empty(emitResult.Diagnostics); } + + [Fact] + public void RunTuple() + { + var source = """ + static class Lib + { + public static string Go() + { + var tuple = (1, 2); + return tuple.ToString(); + } + } + """; + + var references = IsCoreClr + ? Net80.References.All + : [.. Net461.References.All, .. Net461.ExtraReferences.All]; + var actual = CompilationUtil.CompileAndRun(source, nameof(RunTuple), references); + Assert.Equal("(1, 2)", actual); + } } diff --git a/Src/Generate/Program.cs b/Src/Generate/Program.cs index 077a67b..be25fa6 100644 --- a/Src/Generate/Program.cs +++ b/Src/Generate/Program.cs @@ -166,7 +166,10 @@ void Net461() var content = GetGeneratedContent( "Net461", [@"microsoft.netframework.referenceassemblies.net461\1.0.3\build\.NETFramework\v4.6.1"], - [@"system.threading.tasks.extensions\4.5.4\lib\net461"]); + [ + @"system.threading.tasks.extensions\4.5.4\lib\net461", + @"system.valuetuple\4.5.0\lib\net461" + ]); var targetDir = Path.Combine(srcPath, "Basic.Reference.Assemblies.Net461"); File.WriteAllText(Path.Combine(targetDir, "Generated.cs"), content.CodeContent, encoding); File.WriteAllText(Path.Combine(targetDir, "Generated.targets"), content.TargetsContent, encoding);