From 3620527a4d77593f04c39bc80a14ac27d63bc6f0 Mon Sep 17 00:00:00 2001 From: Domn Werner Date: Sat, 17 Jan 2026 10:24:57 -0800 Subject: [PATCH 1/5] Remove multitarget on dotnet 8 --- src/Dunet/Dunet.csproj | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Dunet/Dunet.csproj b/src/Dunet/Dunet.csproj index 1be90fe..425bcce 100644 --- a/src/Dunet/Dunet.csproj +++ b/src/Dunet/Dunet.csproj @@ -1,15 +1,15 @@  - - netstandard2.0;net8.0 - enable - enable - 12.0 - True - True - + + netstandard2.0 + enable + enable + 12.0 + True + True + - - - + + + From d4dd2b3a2ff4077a4fda10cfa56291ca7b9b6b2c Mon Sep 17 00:00:00 2001 From: Domn Werner Date: Sat, 17 Jan 2026 10:25:22 -0800 Subject: [PATCH 2/5] Downgrade Microsoft.CodeAnalysis.CSharp to v4.12.0 for better linux compatibility --- src/Dunet.Generator/Dunet.Generator.csproj | 50 +++++++++++----------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/src/Dunet.Generator/Dunet.Generator.csproj b/src/Dunet.Generator/Dunet.Generator.csproj index 943d38c..0f22291 100644 --- a/src/Dunet.Generator/Dunet.Generator.csproj +++ b/src/Dunet.Generator/Dunet.Generator.csproj @@ -1,30 +1,30 @@ - - netstandard2.0 - enable - enable - 12.0 - True - $(NoWarn);NU5128 - true - Dunet.Generator - true - + + netstandard2.0 + enable + enable + 12.0 + True + $(NoWarn);NU5128 + true + Dunet.Generator + true + - - - + + + - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + From 4788311199acfeb52c7e87956398097c6fbfff58 Mon Sep 17 00:00:00 2001 From: Domn Werner Date: Sat, 17 Jan 2026 10:26:02 -0800 Subject: [PATCH 3/5] Simplify compilation setup --- test/Compilation/Compiler.cs | 49 +++++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/test/Compilation/Compiler.cs b/test/Compilation/Compiler.cs index 2505444..bc31fcc 100644 --- a/test/Compilation/Compiler.cs +++ b/test/Compilation/Compiler.cs @@ -1,4 +1,7 @@ -using System.Reflection; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; using Dunet.Generator.UnionGeneration; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; @@ -39,29 +42,35 @@ public static CompilationResult Compile(params string[] sources) ); } - private static CSharpCompilation CreateCompilation(params string[] sources) => - CSharpCompilation.Create( + private static CSharpCompilation CreateCompilation(params string[] sources) + { + // Include metadata references for all currently loaded assemblies that have a physical location. + // This keeps the test compilation environment in sync with the test host and avoids + // manually listing specific runtime assemblies. + var loadedAssemblyPaths = AppDomain.CurrentDomain.GetAssemblies() + .Where(a => !a.IsDynamic && !string.IsNullOrEmpty(a.Location)) + .Select(a => a.Location) + .Distinct() + .ToList(); + + var references = loadedAssemblyPaths + .Select(path => MetadataReference.CreateFromFile(path)) + .ToList(); + + // Ensure the assembly containing UnionAttribute is referenced in case it's not already loaded. + var unionAssemblyLocation = typeof(UnionAttribute).GetTypeInfo().Assembly.Location; + if (!string.IsNullOrEmpty(unionAssemblyLocation) && !loadedAssemblyPaths.Contains(unionAssemblyLocation)) + { + references.Add(MetadataReference.CreateFromFile(unionAssemblyLocation)); + } + + return CSharpCompilation.Create( "compilation", sources.Select(static source => CSharpSyntaxTree.ParseText(source)), - [ - // Resolves to System.Private.CoreLib.dll - MetadataReference.CreateFromFile(typeof(object).GetTypeInfo().Assembly.Location), - // Resolves to System.Runtime.dll, which is needed for the Attribute type - // Can't use typeof(Attribute).GetTypeInfo().Assembly.Location because it resolves to System.Private.CoreLib.dll - MetadataReference.CreateFromFile( - AppDomain - .CurrentDomain.GetAssemblies() - .First(static assembly => - assembly.FullName?.Contains("System.Runtime") is true - ) - .Location - ), - MetadataReference.CreateFromFile( - typeof(UnionAttribute).GetTypeInfo().Assembly.Location - ) - ], + references, new CSharpCompilationOptions(OutputKind.ConsoleApplication) ); + } private static GenerationResult RunGenerator(Microsoft.CodeAnalysis.Compilation compilation) { From 20dab468443fae3dab3fbfcb393b5cd5a03da5cc Mon Sep 17 00:00:00 2001 From: Domn Werner Date: Sat, 17 Jan 2026 10:36:10 -0800 Subject: [PATCH 4/5] Cleanup --- src/Dunet.Generator/Dunet.Generator.csproj | 52 +++++++++++----------- src/Dunet/Dunet.csproj | 22 ++++----- 2 files changed, 37 insertions(+), 37 deletions(-) diff --git a/src/Dunet.Generator/Dunet.Generator.csproj b/src/Dunet.Generator/Dunet.Generator.csproj index 0f22291..94b0479 100644 --- a/src/Dunet.Generator/Dunet.Generator.csproj +++ b/src/Dunet.Generator/Dunet.Generator.csproj @@ -1,30 +1,30 @@ - - - netstandard2.0 - enable - enable - 12.0 - True - $(NoWarn);NU5128 - true - Dunet.Generator - true - + + + netstandard2.0 + enable + enable + 12.0 + True + $(NoWarn);NU5128 + true + Dunet.Generator + true + - - - + + + - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/src/Dunet/Dunet.csproj b/src/Dunet/Dunet.csproj index 425bcce..32be7c8 100644 --- a/src/Dunet/Dunet.csproj +++ b/src/Dunet/Dunet.csproj @@ -1,15 +1,15 @@  - - netstandard2.0 - enable - enable - 12.0 - True - True - + + netstandard2.0 + enable + enable + 12.0 + True + True + - - - + + + From 9bfdfd481bb8b8c3ac53ed01e67e556bda739d04 Mon Sep 17 00:00:00 2001 From: Domn Werner Date: Sat, 17 Jan 2026 10:47:43 -0800 Subject: [PATCH 5/5] Format --- src/Dunet.Generator/Dunet.Generator.csproj | 58 ++++++++++--------- src/Dunet.Generator/IdentifierExtensions.cs | 3 +- src/Dunet.Generator/SyntaxExtensions.cs | 10 ++-- .../RecordDeclarationSyntaxParser.cs | 24 ++++---- .../UnionGeneration/UnionGenerator.cs | 4 +- .../UnionGeneration/UnionSourceBuilder.cs | 4 +- src/Dunet/Dunet.csproj | 28 ++++----- test/Compilation/Compiler.cs | 8 ++- 8 files changed, 72 insertions(+), 67 deletions(-) diff --git a/src/Dunet.Generator/Dunet.Generator.csproj b/src/Dunet.Generator/Dunet.Generator.csproj index 94b0479..a9408a6 100644 --- a/src/Dunet.Generator/Dunet.Generator.csproj +++ b/src/Dunet.Generator/Dunet.Generator.csproj @@ -1,30 +1,32 @@  - - netstandard2.0 - enable - enable - 12.0 - True - $(NoWarn);NU5128 - true - Dunet.Generator - true - - - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - + + netstandard2.0 + enable + enable + 12.0 + True + $(NoWarn);NU5128 + true + Dunet.Generator + true + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/src/Dunet.Generator/IdentifierExtensions.cs b/src/Dunet.Generator/IdentifierExtensions.cs index 1026a97..a9647d5 100644 --- a/src/Dunet.Generator/IdentifierExtensions.cs +++ b/src/Dunet.Generator/IdentifierExtensions.cs @@ -12,8 +12,7 @@ var s when s.StartsWith("@") => identifier, // - Prepend '@' to prevent keyword conflicts. // - Lowercase the first character to abide by C# style rules for method parameter // casing and prevent collision with its type. - [var firstCharacter, .. var rest] - => $"@{char.ToLowerInvariant(firstCharacter)}{rest}", + [var firstCharacter, .. var rest] => $"@{char.ToLowerInvariant(firstCharacter)}{rest}", // If anything else came in, we just return it back and let the caller handle it. _ => identifier, }; diff --git a/src/Dunet.Generator/SyntaxExtensions.cs b/src/Dunet.Generator/SyntaxExtensions.cs index 0912f18..d405710 100644 --- a/src/Dunet.Generator/SyntaxExtensions.cs +++ b/src/Dunet.Generator/SyntaxExtensions.cs @@ -42,14 +42,12 @@ public static string ToKeyword(this Accessibility accessibility) => accessibility switch { Accessibility.Public => "public", - Accessibility.ProtectedOrInternal - or Accessibility.ProtectedOrFriend - => "protected internal", + Accessibility.ProtectedOrInternal or Accessibility.ProtectedOrFriend => + "protected internal", Accessibility.Internal or Accessibility.Friend => "internal", Accessibility.Protected => "protected", - Accessibility.ProtectedAndInternal - or Accessibility.ProtectedAndFriend - => "private protected", + Accessibility.ProtectedAndInternal or Accessibility.ProtectedAndFriend => + "private protected", Accessibility.Private => "private", Accessibility.NotApplicable => "", _ => "", diff --git a/src/Dunet.Generator/UnionGeneration/RecordDeclarationSyntaxParser.cs b/src/Dunet.Generator/UnionGeneration/RecordDeclarationSyntaxParser.cs index 2786a98..cd4e92d 100644 --- a/src/Dunet.Generator/UnionGeneration/RecordDeclarationSyntaxParser.cs +++ b/src/Dunet.Generator/UnionGeneration/RecordDeclarationSyntaxParser.cs @@ -17,9 +17,9 @@ internal static class RecordDeclarationSyntaxParser public static IEnumerable GetTypeParameters( this RecordDeclarationSyntax record ) => - record - .TypeParameterList?.Parameters - .Select(static typeParam => new TypeParameter(typeParam.Identifier.ToString())) ?? []; + record.TypeParameterList?.Parameters.Select(static typeParam => new TypeParameter( + typeParam.Identifier.ToString() + )) ?? []; /// /// Gets the type parameter constraints of this record declaration. @@ -43,15 +43,13 @@ public static IEnumerable GetParameters( this RecordDeclarationSyntax record, SemanticModel semanticModel ) => - record - .ParameterList?.Parameters - .Select(parameter => new Parameter( - Type: new ParameterType( - Identifier: parameter.Type?.ToString() ?? "", - IsInterface: parameter.Type.IsInterfaceType(semanticModel) - ), - Identifier: parameter.Identifier.ToString() - )) ?? []; + record.ParameterList?.Parameters.Select(parameter => new Parameter( + Type: new ParameterType( + Identifier: parameter.Type?.ToString() ?? "", + IsInterface: parameter.Type.IsInterfaceType(semanticModel) + ), + Identifier: parameter.Identifier.ToString() + )) ?? []; /// /// Gets the properties declared in this record. @@ -94,7 +92,7 @@ SemanticModel semanticModel { Identifier = nestedRecord.Identifier.ToString(), TypeParameters = nestedRecord.GetTypeParameters().ToImmutableEquatableArray(), - Parameters = nestedRecord.GetParameters(semanticModel).ToImmutableEquatableArray() + Parameters = nestedRecord.GetParameters(semanticModel).ToImmutableEquatableArray(), }); /// diff --git a/src/Dunet.Generator/UnionGeneration/UnionGenerator.cs b/src/Dunet.Generator/UnionGeneration/UnionGenerator.cs index f7f210a..57f1f72 100644 --- a/src/Dunet.Generator/UnionGeneration/UnionGenerator.cs +++ b/src/Dunet.Generator/UnionGeneration/UnionGenerator.cs @@ -45,8 +45,8 @@ private static void Emit(SourceProductionContext context, UnionDeclaration union var union = UnionSourceBuilder.Build(unionRecord); context.AddSource( unionRecord.TypeParameters.Count == 0 - ? $"{unionRecord.Namespace}.{unionRecord.Name}.g.cs" - : $"{unionRecord.Namespace}.{unionRecord.Name}.{unionRecord.TypeParameters.Count}.g.cs", + ? $"{unionRecord.Namespace}.{unionRecord.Name}.g.cs" + : $"{unionRecord.Namespace}.{unionRecord.Name}.{unionRecord.TypeParameters.Count}.g.cs", SourceText.From(union, Encoding.UTF8) ); diff --git a/src/Dunet.Generator/UnionGeneration/UnionSourceBuilder.cs b/src/Dunet.Generator/UnionGeneration/UnionSourceBuilder.cs index 3e93383..c56d651 100644 --- a/src/Dunet.Generator/UnionGeneration/UnionSourceBuilder.cs +++ b/src/Dunet.Generator/UnionGeneration/UnionSourceBuilder.cs @@ -454,7 +454,9 @@ VariantDeclaration variant ); builder.Append($" TState state"); builder.AppendLine(union.Variants.Count > 0 ? "," : string.Empty); - builder.Append($" global::System.Action {specificVariant.Identifier.ToMethodParameterCase()},"); builder.AppendLine($" global::System.Action @else"); diff --git a/src/Dunet/Dunet.csproj b/src/Dunet/Dunet.csproj index 32be7c8..f2408c7 100644 --- a/src/Dunet/Dunet.csproj +++ b/src/Dunet/Dunet.csproj @@ -1,15 +1,17 @@  - - - netstandard2.0 - enable - enable - 12.0 - True - True - - - - - + + netstandard2.0 + enable + enable + 12.0 + True + True + + + + diff --git a/test/Compilation/Compiler.cs b/test/Compilation/Compiler.cs index bc31fcc..7a8f780 100644 --- a/test/Compilation/Compiler.cs +++ b/test/Compilation/Compiler.cs @@ -47,7 +47,8 @@ private static CSharpCompilation CreateCompilation(params string[] sources) // Include metadata references for all currently loaded assemblies that have a physical location. // This keeps the test compilation environment in sync with the test host and avoids // manually listing specific runtime assemblies. - var loadedAssemblyPaths = AppDomain.CurrentDomain.GetAssemblies() + var loadedAssemblyPaths = AppDomain + .CurrentDomain.GetAssemblies() .Where(a => !a.IsDynamic && !string.IsNullOrEmpty(a.Location)) .Select(a => a.Location) .Distinct() @@ -59,7 +60,10 @@ private static CSharpCompilation CreateCompilation(params string[] sources) // Ensure the assembly containing UnionAttribute is referenced in case it's not already loaded. var unionAssemblyLocation = typeof(UnionAttribute).GetTypeInfo().Assembly.Location; - if (!string.IsNullOrEmpty(unionAssemblyLocation) && !loadedAssemblyPaths.Contains(unionAssemblyLocation)) + if ( + !string.IsNullOrEmpty(unionAssemblyLocation) + && !loadedAssemblyPaths.Contains(unionAssemblyLocation) + ) { references.Add(MetadataReference.CreateFromFile(unionAssemblyLocation)); }