Skip to content

Commit 3865c99

Browse files
authored
Merge pull request #62 from jaredpar/tuple
Support for ValueTuple
2 parents 5bcaa26 + 269df57 commit 3865c99

File tree

9 files changed

+148
-3
lines changed

9 files changed

+148
-3
lines changed

.github/workflows/dotnet.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ jobs:
2929
run: dotnet pack -p:PackageOutputPath="${GITHUB_WORKSPACE}/packages" -p:IncludeSymbols=false -p:RepositoryCommit=${GITHUB_SHA} -p:PackageVersion="0.0.0.1"
3030

3131
- name: Test
32-
run: dotnet test --no-build --verbosity normal
32+
run: dotnet test --framework net8.0 --no-build --verbosity normal
3333

3434
- name: Upload Binary Log
3535
uses: actions/upload-artifact@v3

Src/Basic.Reference.Assemblies.Net461/Basic.Reference.Assemblies.Net461.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
<ItemGroup>
99
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies.net461" Version="1.0.3" IncludeAssets="none" PrivateAssets="all" GeneratePathProperty="true" />
1010
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.5.4" IncludeAssets="none" PrivateAssets="all" GeneratePathProperty="true" />
11+
<PackageReference Include="System.ValueTuple" Version="4.5.0" IncludeAssets="none" PrivateAssets="all" GeneratePathProperty="true" />
1112
</ItemGroup>
1213

1314
<Import Project="Generated.targets" />

Src/Basic.Reference.Assemblies.Net461/Generated.cs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4476,6 +4476,11 @@ public static class ExtraReferenceInfos
44764476
/// The <see cref="ReferenceInfo"/> for System.Threading.Tasks.Extensions.dll
44774477
/// </summary>
44784478
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"));
4479+
4480+
/// <summary>
4481+
/// The <see cref="ReferenceInfo"/> for System.ValueTuple.dll
4482+
/// </summary>
4483+
public static ReferenceInfo SystemValueTuple => new ReferenceInfo("System.ValueTuple.dll", Resources.SystemValueTuple, Net461.ExtraReferences.SystemValueTuple, global::System.Guid.Parse("1aa5ee86-d143-43bd-94ec-c0749ff98222"));
44794484
private static ImmutableArray<ReferenceInfo> _all;
44804485
public static ImmutableArray<ReferenceInfo> All
44814486
{
@@ -4486,6 +4491,7 @@ public static ImmutableArray<ReferenceInfo> All
44864491
_all =
44874492
[
44884493
SystemThreadingTasksExtensions,
4494+
SystemValueTuple,
44894495
];
44904496
}
44914497
return _all;
@@ -4517,6 +4523,23 @@ public static PortableExecutableReference SystemThreadingTasksExtensions
45174523
}
45184524
}
45194525

4526+
private static PortableExecutableReference? _SystemValueTuple;
4527+
4528+
/// <summary>
4529+
/// The <see cref="PortableExecutableReference"/> for System.ValueTuple.dll
4530+
/// </summary>
4531+
public static PortableExecutableReference SystemValueTuple
4532+
{
4533+
get
4534+
{
4535+
if (_SystemValueTuple is null)
4536+
{
4537+
_SystemValueTuple = AssemblyMetadata.CreateFromImage(Resources.SystemValueTuple).GetReference(filePath: "System.ValueTuple.dll", display: "System.ValueTuple (net461)");
4538+
}
4539+
return _SystemValueTuple;
4540+
}
4541+
}
4542+
45204543
private static ImmutableArray<PortableExecutableReference> _all;
45214544
public static ImmutableArray<PortableExecutableReference> All
45224545
{
@@ -4527,6 +4550,7 @@ public static ImmutableArray<PortableExecutableReference> All
45274550
_all =
45284551
[
45294552
SystemThreadingTasksExtensions,
4553+
SystemValueTuple,
45304554
];
45314555
}
45324556
return _all;
@@ -5649,6 +5673,12 @@ public static class Resources
56495673
public static byte[] SystemThreadingTasksExtensions => ResourceLoader.GetOrCreateResource(ref _SystemThreadingTasksExtensions, "net461.System.Threading.Tasks.Extensions");
56505674
private static byte[]? _SystemThreadingTasksExtensions;
56515675

5676+
/// <summary>
5677+
/// The image bytes for System.ValueTuple.dll
5678+
/// </summary>
5679+
public static byte[] SystemValueTuple => ResourceLoader.GetOrCreateResource(ref _SystemValueTuple, "net461.System.ValueTuple");
5680+
private static byte[]? _SystemValueTuple;
5681+
56525682

56535683
}
56545684
}

Src/Basic.Reference.Assemblies.Net461/Generated.targets

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -740,5 +740,9 @@
740740
<LogicalName>net461.System.Threading.Tasks.Extensions</LogicalName>
741741
<Link>Resources\net461\System.Threading.Tasks.Extensions.dll</Link>
742742
</EmbeddedResource>
743+
<EmbeddedResource Include="$(NuGetPackageRoot)\system.valuetuple\4.5.0\lib\net461\System.ValueTuple.dll" WithCulture="false">
744+
<LogicalName>net461.System.ValueTuple</LogicalName>
745+
<Link>Resources\net461\System.ValueTuple.dll</Link>
746+
</EmbeddedResource>
743747
</ItemGroup>
744748
</Project>

Src/Basic.Reference.Assemblies.UnitTests/Basic.Reference.Assemblies.UnitTests.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFramework>net8.0</TargetFramework>
4+
<TargetFrameworks>net8.0;net472</TargetFrameworks>
55
<IsPackable>false</IsPackable>
66
<RollForward>LatestMajor</RollForward>
77
</PropertyGroup>
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
using Microsoft.CodeAnalysis;
2+
using Microsoft.CodeAnalysis.CSharp;
3+
using Microsoft.CodeAnalysis.Operations;
4+
using System;
5+
using System.Collections.Generic;
6+
using System.IO;
7+
using System.Linq;
8+
using System.Reflection;
9+
using System.Text;
10+
using System.Threading.Tasks;
11+
12+
namespace Basic.Reference.Assemblies.UnitTests;
13+
internal static class CompilationUtil
14+
{
15+
public static MemoryStream CompileToLibrary(string code, string assemblyName, IEnumerable<MetadataReference> references)
16+
{
17+
var options = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary);
18+
var compilation = CSharpCompilation.Create(
19+
assemblyName,
20+
[CSharpSyntaxTree.ParseText(code)],
21+
references,
22+
options);
23+
24+
var peStream = new MemoryStream();
25+
var emitResult = compilation.Emit(peStream);
26+
if (!emitResult.Success)
27+
{
28+
throw new Exception(GetMessage(emitResult.Diagnostics));
29+
}
30+
31+
peStream.Position = 0;
32+
return peStream;
33+
34+
static string GetMessage(IEnumerable<Diagnostic> diagnostics)
35+
{
36+
var builder = new StringBuilder();
37+
builder.AppendLine("Compilation failed with the following errors:");
38+
foreach (var d in diagnostics)
39+
{
40+
builder.AppendLine(d.ToString());
41+
}
42+
return builder.ToString();
43+
}
44+
}
45+
46+
public static Assembly CompileToLibraryAndLoad(string code, string assemblyName, IEnumerable<MetadataReference> references)
47+
{
48+
var stream = CompileToLibrary(code, assemblyName, references);
49+
return Load(stream, assemblyName);
50+
}
51+
52+
/// <summary>
53+
/// Compile and run the code expecting to find a static Lib.Go method
54+
/// </summary>
55+
public static string? CompileAndRun(string code, string assemblyName, IEnumerable<MetadataReference> references)
56+
{
57+
var assembly = CompileToLibraryAndLoad(code, assemblyName, references);
58+
var libType = assembly
59+
.GetTypes()
60+
.Where(x => x.Name == "Lib")
61+
.Single();
62+
var method = libType.GetMethod("Go", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
63+
var obj = method!.Invoke(null, null);
64+
return (string?)obj;
65+
}
66+
67+
public static Assembly Load(MemoryStream stream, string assemblyName)
68+
{
69+
stream.Position = 0;
70+
#if NET
71+
var alc = new System.Runtime.Loader.AssemblyLoadContext(assemblyName);
72+
return alc.LoadFromStream(stream);
73+
#else
74+
return Assembly.Load(stream.ToArray());
75+
#endif
76+
}
77+
}

Src/Basic.Reference.Assemblies.UnitTests/Extensions.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
using Microsoft.CodeAnalysis;
2+
using Microsoft.CodeAnalysis.CSharp;
23
using System;
34
using System.Collections.Generic;
5+
using System.IO;
46
using System.Linq;
7+
using System.Reflection;
58
using System.Text;
69
using System.Threading.Tasks;
710

Src/Basic.Reference.Assemblies.UnitTests/SanityUnitTests.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@ namespace Basic.Reference.Assemblies.UnitTests;
1313
public class SanityUnitTests(ITestOutputHelper outputHelper)
1414
{
1515
public ITestOutputHelper TestOutputHelper { get; } = outputHelper;
16+
public bool IsCoreClr =>
17+
#if NET
18+
true;
19+
#else
20+
false;
21+
#endif
1622

1723
[Theory]
1824
[MemberData(nameof(TestData.ApplicationReferences), MemberType = typeof(TestData))]
@@ -176,4 +182,25 @@ static void Main()
176182
Assert.True(emitResult.Success);
177183
Assert.Empty(emitResult.Diagnostics);
178184
}
185+
186+
[Fact]
187+
public void RunTuple()
188+
{
189+
var source = """
190+
static class Lib
191+
{
192+
public static string Go()
193+
{
194+
var tuple = (1, 2);
195+
return tuple.ToString();
196+
}
197+
}
198+
""";
199+
200+
var references = IsCoreClr
201+
? Net80.References.All
202+
: [.. Net461.References.All, .. Net461.ExtraReferences.All];
203+
var actual = CompilationUtil.CompileAndRun(source, nameof(RunTuple), references);
204+
Assert.Equal("(1, 2)", actual);
205+
}
179206
}

Src/Generate/Program.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,10 @@ void Net461()
166166
var content = GetGeneratedContent(
167167
"Net461",
168168
[@"microsoft.netframework.referenceassemblies.net461\1.0.3\build\.NETFramework\v4.6.1"],
169-
[@"system.threading.tasks.extensions\4.5.4\lib\net461"]);
169+
[
170+
@"system.threading.tasks.extensions\4.5.4\lib\net461",
171+
@"system.valuetuple\4.5.0\lib\net461"
172+
]);
170173
var targetDir = Path.Combine(srcPath, "Basic.Reference.Assemblies.Net461");
171174
File.WriteAllText(Path.Combine(targetDir, "Generated.cs"), content.CodeContent, encoding);
172175
File.WriteAllText(Path.Combine(targetDir, "Generated.targets"), content.TargetsContent, encoding);

0 commit comments

Comments
 (0)