diff --git a/README.md b/README.md index 3db132589..4628d325e 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ -# RSCG - 272 Examples of Roslyn Source Code Generators / 16 created by Microsoft / +# RSCG - 273 Examples of Roslyn Source Code Generators / 16 created by Microsoft / -The RSCG_Examples repository is a comprehensive documentation system that automatically processes and showcases 272 Roslyn Source Code Generator (RSCG) examples. The system transforms individual RSCG projects into structured documentation with code examples and cross-referenced content with a searchable website and code example exports. +The RSCG_Examples repository is a comprehensive documentation system that automatically processes and showcases 273 Roslyn Source Code Generator (RSCG) examples. The system transforms individual RSCG projects into structured documentation with code examples and cross-referenced content with a searchable website and code example exports. This system serves as both a learning resource for .NET developers interested in source generators and an automated pipeline for maintaining up-to-date documentation about the RSCG ecosystem -## Latest Update : 2026-06-29 => 29 June 2026 +## Latest Update : 2026-06-30 => 30 June 2026 If you want to see examples with code, please click ***[List V2](https://ignatandrei.github.io/RSCG_Examples/v2/docs/List-of-RSCG)*** @@ -24,8 +24,30 @@ If you want to be notified each time I add a new RSCG example , please click htt ## Content -Those are the 272 Roslyn Source Code Generators that I have tested you can see and download source code example. +Those are the 273 Roslyn Source Code Generators that I have tested you can see and download source code example. ( including 16 from Microsoft ) +### 273. [ScottEncodingGenerator](https://ignatandrei.github.io/RSCG_Examples/v2/docs/ScottEncodingGenerator) , in the [FunctionalProgramming](https://ignatandrei.github.io/RSCG_Examples/v2/docs/rscg-examples#functionalprogramming) category + +Generated on : 2026-06-30 => 30 June 2026 + +
+ Expand + + + +Author: Georgiy Petrov + +Roslyn incremental source generator for partial interfaces and abstract partial classes that generates Match methods, nested case implementations, and companion module helpers for Scott-encoded types. + +Nuget: [https://www.nuget.org/packages/ScottEncodingGenerator/](https://www.nuget.org/packages/ScottEncodingGenerator/) + + +Link: [https://ignatandrei.github.io/RSCG_Examples/v2/docs/ScottEncodingGenerator](https://ignatandrei.github.io/RSCG_Examples/v2/docs/ScottEncodingGenerator) + +Source: [https://github.com/Georgiy-Petrov/ScottEncodingGenerator](https://github.com/Georgiy-Petrov/ScottEncodingGenerator) + +
+ ### 272. [AlephMapper](https://ignatandrei.github.io/RSCG_Examples/v2/docs/AlephMapper) , in the [Database](https://ignatandrei.github.io/RSCG_Examples/v2/docs/rscg-examples#database) category Generated on : 2026-06-29 => 29 June 2026 diff --git a/later.md b/later.md index 8ee650ce5..6609fbb71 100644 --- a/later.md +++ b/later.md @@ -1,6 +1,6 @@ # Just later -## Latest Update : 2026-06-29 => 29 June 2026 +## Latest Update : 2026-06-30 => 30 June 2026 diff --git a/v2/Generator/MultiGeneratorV2.cs b/v2/Generator/MultiGeneratorV2.cs index a1b9ece95..35e0de32f 100644 --- a/v2/Generator/MultiGeneratorV2.cs +++ b/v2/Generator/MultiGeneratorV2.cs @@ -433,7 +433,10 @@ private async Task GatherData(int nr, string generator, string root Description? desc = null; try { - desc = JsonSerializer.Deserialize(text); + var opt = new JsonSerializerOptions(JsonSerializerOptions.Default); + opt.AllowTrailingCommas = true; + + desc = JsonSerializer.Deserialize(text,opt); } catch (Exception ex) { diff --git a/v2/Generator/all.csv b/v2/Generator/all.csv index a80fea266..5fab7fc6f 100644 --- a/v2/Generator/all.csv +++ b/v2/Generator/all.csv @@ -271,3 +271,4 @@ Nr,Key,Source,Category 270,AssemblyMetadata.Generators, https://github.com/loresoft/AssemblyMetadata.Generators,EnhancementProject 271,TypedStateBuilder.Generator, https://github.com/Georgiy-Petrov/TypedStateBuilder.Generator,Builder 272,AlephMapper, https://github.com/Raffinert/AlephMapper,Database +273,ScottEncodingGenerator, https://github.com/Georgiy-Petrov/ScottEncodingGenerator,FunctionalProgramming diff --git a/v2/RSCGExamplesData/GeneratorDataRec.json b/v2/RSCGExamplesData/GeneratorDataRec.json index d8a16c66c..0c101513a 100644 --- a/v2/RSCGExamplesData/GeneratorDataRec.json +++ b/v2/RSCGExamplesData/GeneratorDataRec.json @@ -1648,5 +1648,11 @@ "Category": 14, "dtStart": "2026-06-29T00:00:00", "show": true + }, + { + "ID":"ScottEncodingGenerator", + "Category": 10, + "dtStart": "2026-06-30T00:00:00", + "show": true } ] \ No newline at end of file diff --git a/v2/book/examples/ScottEncodingGenerator.html b/v2/book/examples/ScottEncodingGenerator.html new file mode 100644 index 000000000..7b4dae35f --- /dev/null +++ b/v2/book/examples/ScottEncodingGenerator.html @@ -0,0 +1,70 @@ + +

RSCG nr 273 : ScottEncodingGenerator

+ +

Info

+Nuget : https://www.nuget.org/packages/ScottEncodingGenerator/ + +

You can find more details at : https://github.com/Georgiy-Petrov/ScottEncodingGenerator

+ +

Author :Georgiy Petrov

+ +

Source: https://github.com/Georgiy-Petrov/ScottEncodingGenerator

+ +

About

+ +Usage 1. You declare a union-like type as an abstract partial class and annotate it with ScottEncoding.2. Inside it, you define each case as a sealed partial nested class (in this sample: Ok and None).3. Your business logic returns one of those cases (Ok when save succeeds, None when it does not).4. Consumer code can handle results either with normal C# pattern matching or with the generated functional matching API.2. What the generator adds1. A Match contract on the parent union type, plus per-case implementations that dispatch to the correct handler.2. A companion module with factory helpers to construct each case (Ok / None) without directly calling constructors.3. A fluent matching flow (IfOk(...).IfNone(...)) built on top of Match.4. A generated ScottEncodingAttribute definition, so the attribute is available at compile time. + +

+ How to use +

+

+ Add reference to the ScottEncodingGenerator in the csproj +

+ + +

This was for me the starting code

+ +
+ I have coded the file Program.cs +
+ +
+ +
+ I have coded the file ResultSave.cs +
+ +
+ +
+ I have coded the file SaveToDatabase.cs +
+ +
+

And here are the generated files

+ +
+ The file generated is global__UnionTypesDemo_ResultSave_T_.ScottEncoding.g.cs +
+ + +
+ The file generated is ScottEncodingAttribute.g.cs +
+ + +

+ You can download the code and this page as pdf from + + https://ignatandrei.github.io/RSCG_Examples/v2/docs/ScottEncodingGenerator + +

+ + +

+ You can see the whole list at + + https://ignatandrei.github.io/RSCG_Examples/v2/docs/List-of-RSCG + +

+ diff --git a/v2/book/list.html b/v2/book/list.html index 72f699aab..35f18431c 100644 --- a/v2/book/list.html +++ b/v2/book/list.html @@ -17,7 +17,7 @@

-This is the list of 272 RSCG with examples => +This is the list of 273 RSCG with examples =>

@@ -1114,6 +1114,10 @@

+ + + +
272 AlephMapper
273ScottEncodingGenerator
diff --git a/v2/book/pandocHTML.yaml b/v2/book/pandocHTML.yaml index b02ef9ebf..bcabfbc43 100644 --- a/v2/book/pandocHTML.yaml +++ b/v2/book/pandocHTML.yaml @@ -286,6 +286,7 @@ input-files: - examples/AssemblyMetadata.Generators.html - examples/TypedStateBuilder.Generator.html - examples/AlephMapper.html +- examples/ScottEncodingGenerator.html # or you may use input-file: with a single value # defaults: diff --git a/v2/docFind.json b/v2/docFind.json index 1e81f34fd..b8e962f3d 100644 --- a/v2/docFind.json +++ b/v2/docFind.json @@ -1630,5 +1630,11 @@ "category": "Database", "href": "/RSCG_Examples/v2/docs/AlephMapper/", "body": "Source generator for creating projectable companions" + }, + { + "title": "ScottEncodingGenerator", + "category": "FunctionalProgramming", + "href": "/RSCG_Examples/v2/docs/ScottEncodingGenerator/", + "body": "Roslyn incremental source generator for partial interfaces and abstract partial classes that generates Match methods, nested case implementations, and companion module helpers for Scott-encoded types." } ] \ No newline at end of file diff --git a/v2/rscg_examples/ScottEncodingGenerator/description.json b/v2/rscg_examples/ScottEncodingGenerator/description.json new file mode 100644 index 000000000..4e9c9a0b2 --- /dev/null +++ b/v2/rscg_examples/ScottEncodingGenerator/description.json @@ -0,0 +1,33 @@ +{ + "generator":{ + "name":"ScottEncodingGenerator", + "nuget":[ + "https://www.nuget.org/packages/ScottEncodingGenerator/" + ], + "link":"https://github.com/Georgiy-Petrov/ScottEncodingGenerator", + "author":"Georgiy Petrov", + "source":"https://github.com/Georgiy-Petrov/ScottEncodingGenerator" + }, + "data":{ + "goodFor":["Usage ", +"1. You declare a union-like type as an abstract partial class and annotate it with ScottEncoding.", +"2. Inside it, you define each case as a sealed partial nested class (in this sample: Ok and None).", +"3. Your business logic returns one of those cases (Ok when save succeeds, None when it does not).", +"4. Consumer code can handle results either with normal C# pattern matching or with the generated functional matching API.", +"", +"2. What the generator adds", +"1. A Match contract on the parent union type, plus per-case implementations that dispatch to the correct handler.", +"2. A companion module with factory helpers to construct each case (Ok / None) without directly calling constructors.", +"3. A fluent matching flow (IfOk(...).IfNone(...)) built on top of Match.", +"4. A generated ScottEncodingAttribute definition, so the attribute is available at compile time." + ], + "csprojDemo":"UnionTypesDemo.csproj", + "csFiles":["Program.cs","ResultSave.cs","SaveToDatabase.cs"], + "excludeDirectoryGenerated":[""], + "includeAdditionalFiles":[""] + }, + "links":{ + "blog":"", + "video":"" + } +} \ No newline at end of file diff --git a/v2/rscg_examples/ScottEncodingGenerator/nuget.txt b/v2/rscg_examples/ScottEncodingGenerator/nuget.txt new file mode 100644 index 000000000..32e59fe71 --- /dev/null +++ b/v2/rscg_examples/ScottEncodingGenerator/nuget.txt @@ -0,0 +1 @@ +Roslyn incremental source generator for partial interfaces and abstract partial classes that generates Match methods, nested case implementations, and companion module helpers for Scott-encoded types. \ No newline at end of file diff --git a/v2/rscg_examples/ScottEncodingGenerator/readme.txt b/v2/rscg_examples/ScottEncodingGenerator/readme.txt new file mode 100644 index 000000000..0e4030e7a --- /dev/null +++ b/v2/rscg_examples/ScottEncodingGenerator/readme.txt @@ -0,0 +1,348 @@ +# ScottEncodingGenerator + +`ScottEncodingGenerator` is a C# source generator for defining closed sets of nested case types and generating a `Match` API for them. + +It targets types marked with `[ScottEncoding]` and generates: + +* a `Match(...)` member on the target type +* per-case `Match` implementations on nested case types +* factory methods for constructing cases +* step-by-step extension methods for building a full match expression + +The generator supports: + +* `partial interface` targets +* `abstract partial class` targets + +It does not support: + +* structs as targets +* generic nested cases +* non-partial nested cases + +[![NuGet](https://img.shields.io/nuget/v/ScottEncodingGenerator.svg?logo=nuget)](https://www.nuget.org/packages/ScottEncodingGenerator) + +## Purpose + +The generator is intended for code shaped like a discriminated union encoded with nested types. + +Instead of manually writing: + +* the common `Match` contract +* one implementation per case +* helper factory methods +* fluent matching helpers + +the generator derives those from the target type and its nested case declarations. + +## Example + +### Input + +```csharp +[ScottEncoding] +public abstract partial class Option +{ + public sealed partial class Some + { + public Some(T value) => Value = value; + public T Value { get; } + } + + public sealed partial class None + { + public None() { } + } +} +``` + +### Generated shape + +The generator adds a `Match` member to the target: + +```csharp +public abstract partial class Option +{ + public abstract TResult Match( + Func.Some, TResult> some, + Func.None, TResult> none); + + public sealed partial class Some : Option + { + public override TResult Match( + Func.Some, TResult> some, + Func.None, TResult> none) + => some(this); + } + + public sealed partial class None : Option + { + public override TResult Match( + Func.Some, TResult> some, + Func.None, TResult> none) + => none(this); + } +} +``` + +It also generates a companion helper type: + +```csharp +public static partial class OptionModule +{ + public static Option Some(T value) => new Option.Some(value); + public static Option None() => new Option.None(); + + public static MatchStep2 IfSome( + this Option value, + Func.Some, TResult> some) + => new(value, some); +} +``` + +Usage: + +```csharp +Option x = OptionModule.Some(10); + +var text = x.Match( + some => $"Some({some.Value})", + none => "None"); +``` + +Or with the generated step API: + +```csharp +var text = x + .IfSome(some => $"Some({some.Value})") + .IfNone(_ => "None"); +``` + +## Interface targets + +The generator also supports interface targets. + +### Input + +```csharp +[ScottEncoding] +public partial interface Expr +{ + public sealed partial class Constant + { + public Constant(int value) => Value = value; + public int Value { get; } + } + + public sealed partial class Add + { + public Add(Expr left, Expr right) + { + Left = left; + Right = right; + } + + public Expr Left { get; } + public Expr Right { get; } + } +} +``` + +### Generated shape + +For interfaces, the generator emits: + +* a `Match(...)` declaration on the interface +* nested case classes implementing the interface +* helper factories in `ExprModule` + +Example use: + +```csharp +Expr expr = ExprModule.Add( + ExprModule.Constant(1), + ExprModule.Constant(2)); + +var value = expr.Match( + constant => constant.Value, + add => add.Left.Match( + l => l.Value, + _ => 0) + + add.Right.Match( + r => r.Value, + _ => 0)); +``` + +## Rules + +A target type must: + +* be marked with `[ScottEncoding]` +* be `partial` +* be either: + + * an `abstract partial class`, or + * a `partial interface` + +A nested case type must: + +* be declared inside the target +* be a non-generic class +* be `partial` +* be non-abstract +* expose at least one accessible instance constructor + +For class targets, a nested case may: + +* omit an explicit base type, or +* inherit from the target type + +For interface targets, a nested case may: + +* omit an explicit base type, or +* implement the target interface + +A nested case must not specify an unrelated base type. + +## Factories + +For each accessible constructor on each case, the generator emits a factory method in `Module`. + +Example: + +```csharp +public sealed partial class Error +{ + public Error(string message) => Message = message; + public string Message { get; } +} +``` + +Generates a factory similar to: + +```csharp +public static Result Error(string message) => new Result.Error(message); +``` + +If a case has multiple accessible constructors, additional factory methods are emitted with suffixes derived from constructor parameters or an index. + +## Matching API + +The generated `Match(...)` method takes one delegate per case, in declaration order. + +For a target with cases: + +* `Success` +* `Failure` +* `Loading` + +the generated signature is shaped like: + +```csharp +TResult Match( + Func success, + Func failure, + Func loading); +``` + +The fluent step API follows the same order: + +```csharp +value + .IfSuccess(...) + .IfFailure(...) + .IfLoading(...); +``` + +## Diagnostics + +The generator reports the following diagnostics. + +### `SCOTT001` + +Target is not valid. + +Raised when the target is not: + +* partial +* an interface +* or an abstract class + +### `SCOTT002` + +No valid cases were found. + +Raised when the target does not declare any usable nested case types. + +### `SCOTT003` + +A nested case has an invalid shape. + +Raised when a case is not a: + +* partial class +* non-generic class +* non-abstract class + +### `SCOTT004` + +A nested case has no accessible instance constructor. + +### `SCOTT005` + +A nested case has an invalid relationship to the target. + +Raised when a case declares an unrelated base type. + +### `SCOTT006` + +The target already declares a conflicting `Match` method. + +## Generated files + +The generator emits: + +* `ScottEncodingAttribute.g.cs` +* one generated file per valid target, named from the target symbol + +The generated code enables nullable references with: + +```csharp +#nullable enable +``` + +## Notes + +* Cases are processed in a stable order based on syntax location. +* The helper type is named `Module`. +* The helper type is generated as `static partial`. +* Matching delegates use fully qualified type names in generated code. +* The generated API preserves target type parameters and constraint clauses. + +## Minimal example + +```csharp +[ScottEncoding] +public abstract partial class BoolLike +{ + public sealed partial class True + { + public True() { } + } + + public sealed partial class False + { + public False() { } + } +} +``` + +Usage: + +```csharp +BoolLike value = BoolLikeModule.True(); + +var result = value.Match( + @true => 1, + @false => 0); +``` \ No newline at end of file diff --git a/v2/rscg_examples/ScottEncodingGenerator/src/.tours/ScottEncodingGenerator.tour b/v2/rscg_examples/ScottEncodingGenerator/src/.tours/ScottEncodingGenerator.tour new file mode 100644 index 000000000..a25624330 --- /dev/null +++ b/v2/rscg_examples/ScottEncodingGenerator/src/.tours/ScottEncodingGenerator.tour @@ -0,0 +1,48 @@ + +{ + "$schema": "https://aka.ms/codetour-schema", + "title": "ScottEncodingGenerator", + "steps": + [ + { + "file": "UnionTypesDemo/UnionTypesDemo.csproj", + "description": "First, we add Nuget [ScottEncodingGenerator](https://www.nuget.org/packages/ScottEncodingGenerator/) in csproj ", + "pattern": "ScottEncodingGenerator" + } + + ,{ + "file": "UnionTypesDemo/SaveToDatabase.cs", + "description": "File SaveToDatabase.cs ", + "pattern": "this is the code" + } + + ,{ + "file": "UnionTypesDemo/ResultSave.cs", + "description": "File ResultSave.cs ", + "pattern": "this is the code" + } + + ,{ + "file": "UnionTypesDemo/Program.cs", + "description": "File Program.cs \r\n>> dotnet run --project UnionTypesDemo/UnionTypesDemo.csproj ", + "pattern": "this is the code" + } + + + ,{ + "file": "UnionTypesDemo/obj/GX/ScottEncodingGenerator/ScottEncodingGenerator.ScottEncodingGenerator/ScottEncodingAttribute.g.cs", + "description": "Generated File 2 from 2 : ScottEncodingAttribute.g.cs ", + "line": 1 + } + + ,{ + "file": "UnionTypesDemo/obj/GX/ScottEncodingGenerator/ScottEncodingGenerator.ScottEncodingGenerator/global__UnionTypesDemo_ResultSave_T_.ScottEncoding.g.cs", + "description": "Generated File 1 from 2 : global__UnionTypesDemo_ResultSave_T_.ScottEncoding.g.cs ", + "line": 1 + } + + ], + + "ref": "main" + +} \ No newline at end of file diff --git a/v2/rscg_examples/ScottEncodingGenerator/src/UnionTypesDemo.sln b/v2/rscg_examples/ScottEncodingGenerator/src/UnionTypesDemo.sln new file mode 100644 index 000000000..d7021d30f --- /dev/null +++ b/v2/rscg_examples/ScottEncodingGenerator/src/UnionTypesDemo.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.7.34221.43 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnionTypesDemo", "UnionTypesDemo\UnionTypesDemo.csproj", "{B3F52D30-D0FB-4DF2-B494-6B903B16613D}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B3F52D30-D0FB-4DF2-B494-6B903B16613D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B3F52D30-D0FB-4DF2-B494-6B903B16613D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B3F52D30-D0FB-4DF2-B494-6B903B16613D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B3F52D30-D0FB-4DF2-B494-6B903B16613D}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {7C63CD9F-20A2-4EAB-9766-127A7184E23B} + EndGlobalSection +EndGlobal diff --git a/v2/rscg_examples/ScottEncodingGenerator/src/UnionTypesDemo/Program.cs b/v2/rscg_examples/ScottEncodingGenerator/src/UnionTypesDemo/Program.cs new file mode 100644 index 000000000..9b0d0773a --- /dev/null +++ b/v2/rscg_examples/ScottEncodingGenerator/src/UnionTypesDemo/Program.cs @@ -0,0 +1,17 @@ +using UnionTypesDemo; + +Console.WriteLine("Save or not"); +ResultSave data = SaveToDatabase.Save(0); +var message= data switch +{ + ResultSave.Ok ok => $"Saved {ok.Value}", + ResultSave.None => "Not found", +}; +Console.WriteLine(message); +data = SaveToDatabase.Save(1); +message = data.Match( + + ok => $"Saved {ok.Value}", + none => "Not found" + ); +Console.WriteLine(message); diff --git a/v2/rscg_examples/ScottEncodingGenerator/src/UnionTypesDemo/ResultSave.cs b/v2/rscg_examples/ScottEncodingGenerator/src/UnionTypesDemo/ResultSave.cs new file mode 100644 index 000000000..1e06221b2 --- /dev/null +++ b/v2/rscg_examples/ScottEncodingGenerator/src/UnionTypesDemo/ResultSave.cs @@ -0,0 +1,22 @@ + + +namespace UnionTypesDemo; + + +[ScottEncoding] +public abstract partial class ResultSave +{ + + public sealed partial class Ok + { + public Ok(T value) => Value = value; + public T Value { get; } + } + + public sealed partial class None + { + public None() { } + } + +} + diff --git a/v2/rscg_examples/ScottEncodingGenerator/src/UnionTypesDemo/SaveToDatabase.cs b/v2/rscg_examples/ScottEncodingGenerator/src/UnionTypesDemo/SaveToDatabase.cs new file mode 100644 index 000000000..7d7a24813 --- /dev/null +++ b/v2/rscg_examples/ScottEncodingGenerator/src/UnionTypesDemo/SaveToDatabase.cs @@ -0,0 +1,16 @@ +namespace UnionTypesDemo; + +public class SaveToDatabase +{ + public static ResultSave Save(int i) + { + + if (i == 0) + { + return new ResultSave.None(); + } + return new ResultSave.Ok(i); + } +} + + diff --git a/v2/rscg_examples/ScottEncodingGenerator/src/UnionTypesDemo/UnionTypesDemo.csproj b/v2/rscg_examples/ScottEncodingGenerator/src/UnionTypesDemo/UnionTypesDemo.csproj new file mode 100644 index 000000000..94994bfdd --- /dev/null +++ b/v2/rscg_examples/ScottEncodingGenerator/src/UnionTypesDemo/UnionTypesDemo.csproj @@ -0,0 +1,21 @@ + + + + Exe + net10.0 + enable + enable + + + + true + $(BaseIntermediateOutputPath)\GX + + + + + + + + + diff --git a/v2/rscg_examples/ScottEncodingGenerator/video.json b/v2/rscg_examples/ScottEncodingGenerator/video.json new file mode 100644 index 000000000..0840f2523 --- /dev/null +++ b/v2/rscg_examples/ScottEncodingGenerator/video.json @@ -0,0 +1,39 @@ +{ + "scriptName": "ScottEncodingGenerator", + "steps": +[ + {"typeStep":"exec","arg":"clipchamp.exe launch"}, + {"typeStep":"text","arg": "Welcome to Roslyn Examples"}, + {"typeStep":"text","arg":"If you want to see more examples , see List Of RSCG"}, + {"typeStep":"browser","arg":"https://ignatandrei.github.io/RSCG_Examples/v2/docs/List-of-RSCG"}, + {"typeStep":"text","arg": "My name is Andrei Ignat and I am deeply fond of Roslyn Source Code Generator. "}, + +{"typeStep":"text","arg": "Today I will present ScottEncodingGenerator . Usage 1. You declare a union-like type as an abstract partial class and annotate it with ScottEncoding.2. Inside it, you define each case as a sealed partial nested class (in this sample: Ok and None).3. Your business logic returns one of those cases (Ok when save succeeds, None when it does not).4. Consumer code can handle results either with normal C# pattern matching or with the generated functional matching API.2. What the generator adds1. A Match contract on the parent union type, plus per-case implementations that dispatch to the correct handler.2. A companion module with factory helpers to construct each case (Ok / None) without directly calling constructors.3. A fluent matching flow (IfOk(...).IfNone(...)) built on top of Match.4. A generated ScottEncodingAttribute definition, so the attribute is available at compile time. ."}, +{"typeStep":"browser","arg":"https://www.nuget.org/packages/ScottEncodingGenerator/"}, +{"typeStep":"text","arg": "The whole example is here"}, +{"typeStep":"browser","arg":"https://ignatandrei.github.io/RSCG_Examples/v2/docs/ScottEncodingGenerator"}, +{"typeStep":"text","arg": "You can download the code from here"}, +{"typeStep":"browser","arg":"https://ignatandrei.github.io/RSCG_Examples/v2/docs/ScottEncodingGenerator#download-example-net--c-"}, +{"typeStep":"text","arg":"Here is the code downloaded "}, +{"typeStep":"exec","arg":"explorer.exe /select,D:\\gth\\RSCG_Examples\\v2\\rscg_examples\\ScottEncodingGenerator\\src\\UnionTypesDemo.sln"}, +{"typeStep":"text","arg": "So , let's start the project with Visual Studio Code "}, +{"typeStep":"stepvscode","arg": "-n D:\\gth\\RSCG_Examples\\v2\\rscg_examples\\ScottEncodingGenerator\\src"}, + +{"typeStep":"text","arg": "To use it ,you will put the Nuget ScottEncodingGenerator into the csproj "}, + +{"typeStep":"stepvscode","arg": "-r -g D:\\gth\\RSCG_Examples\\v2\\rscg_examples\\ScottEncodingGenerator\\src\\UnionTypesDemo\\UnionTypesDemo.csproj"}, + +{"typeStep":"text","arg": "And now I will show you an example of using ScottEncodingGenerator"}, + +{"typeStep":"hide","arg": "now execute the tour in VSCode"}, +{"typeStep":"tour", "arg": "src/.tours/"}, +{"typeStep":"text","arg":" And I will execute the project"}, +{"typeStep":"showproj", "arg":"UnionTypesDemo.csproj"}, +{"typeStep":"text","arg":" This concludes the project"}, +{"typeStep":"waitseconds","arg":"30"}, +{"typeStep":"text","arg": "Remember, you can download the code from here"}, +{"typeStep":"browser","arg":"https://ignatandrei.github.io/RSCG_Examples/v2/docs/ScottEncodingGenerator#download-example-net--c-", +SpeakTest=" "}, +{"typeStep":"waitseconds","arg":"30"}, +] +} diff --git a/v2/rscg_examples_site/docs/Authors/Georgiy_Petrov.md b/v2/rscg_examples_site/docs/Authors/Georgiy_Petrov.md index f453906c1..0e8938fb6 100644 --- a/v2/rscg_examples_site/docs/Authors/Georgiy_Petrov.md +++ b/v2/rscg_examples_site/docs/Authors/Georgiy_Petrov.md @@ -1,6 +1,6 @@ # Author : Georgiy Petrov -Number RSCG: 3 +Number RSCG: 4 1 [StepwiseBuilderGenerator](/docs/StepwiseBuilderGenerator) [![Nuget](https://img.shields.io/nuget/dt/StepwiseBuilderGenerator?label=StepwiseBuilderGenerator)](https://www.nuget.org/packages/StepwiseBuilderGenerator/) ![GitHub Repo stars](https://img.shields.io/github/stars/Georgiy-Petrov/StepwiseBuilderGenerator?style=social) 2025-03-23 @@ -9,3 +9,5 @@ Number RSCG: 3 3 [TypedStateBuilder.Generator](/docs/TypedStateBuilder.Generator) [![Nuget](https://img.shields.io/nuget/dt/TypedStateBuilder.Generator?label=TypedStateBuilder.Generator)](https://www.nuget.org/packages/TypedStateBuilder.Generator/) ![GitHub Repo stars](https://img.shields.io/github/stars/Georgiy-Petrov/TypedStateBuilder.Generator?style=social) 2026-05-16 + 4 [ScottEncodingGenerator](/docs/ScottEncodingGenerator) [![Nuget](https://img.shields.io/nuget/dt/ScottEncodingGenerator?label=ScottEncodingGenerator)](https://www.nuget.org/packages/ScottEncodingGenerator/) ![GitHub Repo stars](https://img.shields.io/github/stars/Georgiy-Petrov/ScottEncodingGenerator?style=social) 2026-06-30 + diff --git a/v2/rscg_examples_site/docs/Categories/FunctionalProgramming.md b/v2/rscg_examples_site/docs/Categories/FunctionalProgramming.md index 05ad2a145..cb445260e 100644 --- a/v2/rscg_examples_site/docs/Categories/FunctionalProgramming.md +++ b/v2/rscg_examples_site/docs/Categories/FunctionalProgramming.md @@ -1,6 +1,6 @@

FunctionalProgramming

-Number RSCG: 17 +Number RSCG: 18 1 [cachesourcegenerator](/docs/cachesourcegenerator) [![Nuget](https://img.shields.io/nuget/dt/cachesourcegenerator?label=cachesourcegenerator)](https://www.nuget.org/packages/cachesourcegenerator/) ![GitHub Repo stars](https://img.shields.io/github/stars/jeppevammenkristensen/cachesourcegenerator?style=social) 2024-02-14 @@ -26,13 +26,15 @@ Number RSCG: 17 12 [RSCG_Utils_Memo](/docs/RSCG_Utils_Memo) [![Nuget](https://img.shields.io/nuget/dt/rscgutils?label=rscgutils)](https://www.nuget.org/packages/rscgutils) ![GitHub Repo stars](https://img.shields.io/github/stars/ignatandrei/RSCG_Utils?style=social) 2023-08-27 - 13 [Sera.Union](/docs/Sera.Union) [![Nuget](https://img.shields.io/nuget/dt/Sera.Union?label=Sera.Union)](https://www.nuget.org/packages/Sera.Union/) ![GitHub Repo stars](https://img.shields.io/github/stars/sera-net/Sera.Union?style=social) 2024-08-26 + 13 [ScottEncodingGenerator](/docs/ScottEncodingGenerator) [![Nuget](https://img.shields.io/nuget/dt/ScottEncodingGenerator?label=ScottEncodingGenerator)](https://www.nuget.org/packages/ScottEncodingGenerator/) ![GitHub Repo stars](https://img.shields.io/github/stars/Georgiy-Petrov/ScottEncodingGenerator?style=social) 2026-06-30 - 14 [Sundew.DiscriminatedUnions](/docs/Sundew.DiscriminatedUnions) [![Nuget](https://img.shields.io/nuget/dt/Sundew.DiscriminatedUnions?label=Sundew.DiscriminatedUnions)](https://www.nuget.org/packages/Sundew.DiscriminatedUnions/) ![GitHub Repo stars](https://img.shields.io/github/stars/sundews/Sundew.DiscriminatedUnions?style=social) 2026-02-14 + 14 [Sera.Union](/docs/Sera.Union) [![Nuget](https://img.shields.io/nuget/dt/Sera.Union?label=Sera.Union)](https://www.nuget.org/packages/Sera.Union/) ![GitHub Repo stars](https://img.shields.io/github/stars/sera-net/Sera.Union?style=social) 2024-08-26 - 15 [TypeUtilities](/docs/TypeUtilities) [![Nuget](https://img.shields.io/nuget/dt/TypeUtilities?label=TypeUtilities)](https://www.nuget.org/packages/TypeUtilities/) ![GitHub Repo stars](https://img.shields.io/github/stars/DragonsLord/TypeUtilities?style=social) 2024-03-05 + 15 [Sundew.DiscriminatedUnions](/docs/Sundew.DiscriminatedUnions) [![Nuget](https://img.shields.io/nuget/dt/Sundew.DiscriminatedUnions?label=Sundew.DiscriminatedUnions)](https://www.nuget.org/packages/Sundew.DiscriminatedUnions/) ![GitHub Repo stars](https://img.shields.io/github/stars/sundews/Sundew.DiscriminatedUnions?style=social) 2026-02-14 - 16 [UnionGen](/docs/UnionGen) [![Nuget](https://img.shields.io/nuget/dt/UnionGen?label=UnionGen)](https://www.nuget.org/packages/UnionGen/) ![GitHub Repo stars](https://img.shields.io/github/stars/markushaslinger/union_source_generator?style=social) 2024-04-05 + 16 [TypeUtilities](/docs/TypeUtilities) [![Nuget](https://img.shields.io/nuget/dt/TypeUtilities?label=TypeUtilities)](https://www.nuget.org/packages/TypeUtilities/) ![GitHub Repo stars](https://img.shields.io/github/stars/DragonsLord/TypeUtilities?style=social) 2024-03-05 - 17 [UnionsGenerator](/docs/UnionsGenerator) [![Nuget](https://img.shields.io/nuget/dt/RhoMicro.CodeAnalysis.UnionsGenerator?label=RhoMicro.CodeAnalysis.UnionsGenerator)](https://www.nuget.org/packages/RhoMicro.CodeAnalysis.UnionsGenerator) ![GitHub Repo stars](https://img.shields.io/github/stars/PaulBraetz/RhoMicro.CodeAnalysis?style=social) 2024-02-18 + 17 [UnionGen](/docs/UnionGen) [![Nuget](https://img.shields.io/nuget/dt/UnionGen?label=UnionGen)](https://www.nuget.org/packages/UnionGen/) ![GitHub Repo stars](https://img.shields.io/github/stars/markushaslinger/union_source_generator?style=social) 2024-04-05 + + 18 [UnionsGenerator](/docs/UnionsGenerator) [![Nuget](https://img.shields.io/nuget/dt/RhoMicro.CodeAnalysis.UnionsGenerator?label=RhoMicro.CodeAnalysis.UnionsGenerator)](https://www.nuget.org/packages/RhoMicro.CodeAnalysis.UnionsGenerator) ![GitHub Repo stars](https://img.shields.io/github/stars/PaulBraetz/RhoMicro.CodeAnalysis?style=social) 2024-02-18 \ No newline at end of file diff --git a/v2/rscg_examples_site/docs/Categories/_PrimitiveFunctionalProgramming.mdx b/v2/rscg_examples_site/docs/Categories/_PrimitiveFunctionalProgramming.mdx index b61057fce..d6a04a48e 100644 --- a/v2/rscg_examples_site/docs/Categories/_PrimitiveFunctionalProgramming.mdx +++ b/v2/rscg_examples_site/docs/Categories/_PrimitiveFunctionalProgramming.mdx @@ -24,15 +24,17 @@ 12 [RSCG_Utils_Memo](/docs/RSCG_Utils_Memo) [![Nuget](https://img.shields.io/nuget/dt/rscgutils?label=rscgutils)](https://www.nuget.org/packages/rscgutils) ![GitHub Repo stars](https://img.shields.io/github/stars/ignatandrei/RSCG_Utils?style=social) 2023-08-27 - 13 [Sera.Union](/docs/Sera.Union) [![Nuget](https://img.shields.io/nuget/dt/Sera.Union?label=Sera.Union)](https://www.nuget.org/packages/Sera.Union/) ![GitHub Repo stars](https://img.shields.io/github/stars/sera-net/Sera.Union?style=social) 2024-08-26 + 13 [ScottEncodingGenerator](/docs/ScottEncodingGenerator) [![Nuget](https://img.shields.io/nuget/dt/ScottEncodingGenerator?label=ScottEncodingGenerator)](https://www.nuget.org/packages/ScottEncodingGenerator/) ![GitHub Repo stars](https://img.shields.io/github/stars/Georgiy-Petrov/ScottEncodingGenerator?style=social) 2026-06-30 - 14 [Sundew.DiscriminatedUnions](/docs/Sundew.DiscriminatedUnions) [![Nuget](https://img.shields.io/nuget/dt/Sundew.DiscriminatedUnions?label=Sundew.DiscriminatedUnions)](https://www.nuget.org/packages/Sundew.DiscriminatedUnions/) ![GitHub Repo stars](https://img.shields.io/github/stars/sundews/Sundew.DiscriminatedUnions?style=social) 2026-02-14 + 14 [Sera.Union](/docs/Sera.Union) [![Nuget](https://img.shields.io/nuget/dt/Sera.Union?label=Sera.Union)](https://www.nuget.org/packages/Sera.Union/) ![GitHub Repo stars](https://img.shields.io/github/stars/sera-net/Sera.Union?style=social) 2024-08-26 - 15 [TypeUtilities](/docs/TypeUtilities) [![Nuget](https://img.shields.io/nuget/dt/TypeUtilities?label=TypeUtilities)](https://www.nuget.org/packages/TypeUtilities/) ![GitHub Repo stars](https://img.shields.io/github/stars/DragonsLord/TypeUtilities?style=social) 2024-03-05 + 15 [Sundew.DiscriminatedUnions](/docs/Sundew.DiscriminatedUnions) [![Nuget](https://img.shields.io/nuget/dt/Sundew.DiscriminatedUnions?label=Sundew.DiscriminatedUnions)](https://www.nuget.org/packages/Sundew.DiscriminatedUnions/) ![GitHub Repo stars](https://img.shields.io/github/stars/sundews/Sundew.DiscriminatedUnions?style=social) 2026-02-14 - 16 [UnionGen](/docs/UnionGen) [![Nuget](https://img.shields.io/nuget/dt/UnionGen?label=UnionGen)](https://www.nuget.org/packages/UnionGen/) ![GitHub Repo stars](https://img.shields.io/github/stars/markushaslinger/union_source_generator?style=social) 2024-04-05 + 16 [TypeUtilities](/docs/TypeUtilities) [![Nuget](https://img.shields.io/nuget/dt/TypeUtilities?label=TypeUtilities)](https://www.nuget.org/packages/TypeUtilities/) ![GitHub Repo stars](https://img.shields.io/github/stars/DragonsLord/TypeUtilities?style=social) 2024-03-05 - 17 [UnionsGenerator](/docs/UnionsGenerator) [![Nuget](https://img.shields.io/nuget/dt/RhoMicro.CodeAnalysis.UnionsGenerator?label=RhoMicro.CodeAnalysis.UnionsGenerator)](https://www.nuget.org/packages/RhoMicro.CodeAnalysis.UnionsGenerator) ![GitHub Repo stars](https://img.shields.io/github/stars/PaulBraetz/RhoMicro.CodeAnalysis?style=social) 2024-02-18 + 17 [UnionGen](/docs/UnionGen) [![Nuget](https://img.shields.io/nuget/dt/UnionGen?label=UnionGen)](https://www.nuget.org/packages/UnionGen/) ![GitHub Repo stars](https://img.shields.io/github/stars/markushaslinger/union_source_generator?style=social) 2024-04-05 + + 18 [UnionsGenerator](/docs/UnionsGenerator) [![Nuget](https://img.shields.io/nuget/dt/RhoMicro.CodeAnalysis.UnionsGenerator?label=RhoMicro.CodeAnalysis.UnionsGenerator)](https://www.nuget.org/packages/RhoMicro.CodeAnalysis.UnionsGenerator) ![GitHub Repo stars](https://img.shields.io/github/stars/PaulBraetz/RhoMicro.CodeAnalysis?style=social) 2024-02-18 ### See category diff --git a/v2/rscg_examples_site/docs/RSCG-Examples/ScottEncodingGenerator.md b/v2/rscg_examples_site/docs/RSCG-Examples/ScottEncodingGenerator.md new file mode 100644 index 000000000..8f7e1ef0c --- /dev/null +++ b/v2/rscg_examples_site/docs/RSCG-Examples/ScottEncodingGenerator.md @@ -0,0 +1,653 @@ +--- +sidebar_position: 2730 +title: 273 - ScottEncodingGenerator +description: Usage +slug: /ScottEncodingGenerator +--- +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import TOCInline from '@theme/TOCInline'; +import SameCategory from '../Categories/_PrimitiveFunctionalProgramming.mdx'; + +# ScottEncodingGenerator by Georgiy Petrov + + + + +## NuGet / site data +[![Nuget](https://img.shields.io/nuget/dt/ScottEncodingGenerator?label=ScottEncodingGenerator)](https://www.nuget.org/packages/ScottEncodingGenerator/) +[![GitHub last commit](https://img.shields.io/github/last-commit/Georgiy-Petrov/ScottEncodingGenerator?label=updated)](https://github.com/Georgiy-Petrov/ScottEncodingGenerator) +![GitHub Repo stars](https://img.shields.io/github/stars/Georgiy-Petrov/ScottEncodingGenerator?style=social) + +## Details + +### Info +:::info + +Name: **ScottEncodingGenerator** + +Roslyn incremental source generator for partial interfaces and abstract partial classes that generates Match methods, nested case implementations, and companion module helpers for Scott-encoded types. + +Author: Georgiy Petrov + +NuGet: +*https://www.nuget.org/packages/ScottEncodingGenerator/* + + +You can find more details at https://github.com/Georgiy-Petrov/ScottEncodingGenerator + +Source: https://github.com/Georgiy-Petrov/ScottEncodingGenerator + +::: + +### Author +:::note +Georgiy Petrov +![Alt text](https://github.com/Georgiy-Petrov.png) +::: + +## Original Readme +:::note + +### ScottEncodingGenerator + +`ScottEncodingGenerator` is a C# source generator for defining closed sets of nested case types and generating a `Match` API for them. + +It targets types marked with `[ScottEncoding]` and generates: + +* a `Match(...)` member on the target type +* per-case `Match` implementations on nested case types +* factory methods for constructing cases +* step-by-step extension methods for building a full match expression + +The generator supports: + +* `partial interface` targets +* `abstract partial class` targets + +It does not support: + +* structs as targets +* generic nested cases +* non-partial nested cases + +[![NuGet](https://img.shields.io/nuget/v/ScottEncodingGenerator.svg?logo=nuget)](https://www.nuget.org/packages/ScottEncodingGenerator) + +###### Purpose + +The generator is intended for code shaped like a discriminated union encoded with nested types. + +Instead of manually writing: + +* the common `Match` contract +* one implementation per case +* helper factory methods +* fluent matching helpers + +the generator derives those from the target type and its nested case declarations. + +###### Example + +######### Input + +```csharp +[ScottEncoding] +public abstract partial class Option +{ + public sealed partial class Some + { + public Some(T value) => Value = value; + public T Value \{ get; } + } + + public sealed partial class None + { + public None() \{ } + } +} +``` + +######### Generated shape + +The generator adds a `Match` member to the target: + +```csharp +public abstract partial class Option +{ + public abstract TResult Match( + Func.Some, TResult> some, + Func.None, TResult> none); + + public sealed partial class Some : Option + { + public override TResult Match( + Func.Some, TResult> some, + Func.None, TResult> none) + => some(this); + } + + public sealed partial class None : Option + { + public override TResult Match( + Func.Some, TResult> some, + Func.None, TResult> none) + => none(this); + } +} +``` + +It also generates a companion helper type: + +```csharp +public static partial class OptionModule +{ + public static Option Some(T value) => new Option.Some(value); + public static Option None() => new Option.None(); + + public static MatchStep2 IfSome( + this Option value, + Func.Some, TResult> some) + => new(value, some); +} +``` + +Usage: + +```csharp +Option x = OptionModule.Some(10); + +var text = x.Match( + some => $"Some({some.Value})", + none => "None"); +``` + +Or with the generated step API: + +```csharp +var text = x + .IfSome(some => $"Some({some.Value})") + .IfNone(_ => "None"); +``` + +###### Interface targets + +The generator also supports interface targets. + +######### Input + +```csharp +[ScottEncoding] +public partial interface Expr +{ + public sealed partial class Constant + { + public Constant(int value) => Value = value; + public int Value \{ get; } + } + + public sealed partial class Add + { + public Add(Expr left, Expr right) + { + Left = left; + Right = right; + } + + public Expr Left \{ get; } + public Expr Right \{ get; } + } +} +``` + +######### Generated shape + +For interfaces, the generator emits: + +* a `Match(...)` declaration on the interface +* nested case classes implementing the interface +* helper factories in `ExprModule` + +Example use: + +```csharp +Expr expr = ExprModule.Add( + ExprModule.Constant(1), + ExprModule.Constant(2)); + +var value = expr.Match( + constant => constant.Value, + add => add.Left.Match( + l => l.Value, + _ => 0) + + add.Right.Match( + r => r.Value, + _ => 0)); +``` + +###### Rules + +A target type must: + +* be marked with `[ScottEncoding]` +* be `partial` +* be either: + + * an `abstract partial class`, or + * a `partial interface` + +A nested case type must: + +* be declared inside the target +* be a non-generic class +* be `partial` +* be non-abstract +* expose at least one accessible instance constructor + +For class targets, a nested case may: + +* omit an explicit base type, or +* inherit from the target type + +For interface targets, a nested case may: + +* omit an explicit base type, or +* implement the target interface + +A nested case must not specify an unrelated base type. + +###### Factories + +For each accessible constructor on each case, the generator emits a factory method in `Module`. + +Example: + +```csharp +public sealed partial class Error +{ + public Error(string message) => Message = message; + public string Message \{ get; } +} +``` + +Generates a factory similar to: + +```csharp +public static Result Error(string message) => new Result.Error(message); +``` + +If a case has multiple accessible constructors, additional factory methods are emitted with suffixes derived from constructor parameters or an index. + +###### Matching API + +The generated `Match(...)` method takes one delegate per case, in declaration order. + +For a target with cases: + +* `Success` +* `Failure` +* `Loading` + +the generated signature is shaped like: + +```csharp +TResult Match( + Func success, + Func failure, + Func loading); +``` + +The fluent step API follows the same order: + +```csharp +value + .IfSuccess(...) + .IfFailure(...) + .IfLoading(...); +``` + +###### Diagnostics + +The generator reports the following diagnostics. + +######### `SCOTT001` + +Target is not valid. + +Raised when the target is not: + +* partial +* an interface +* or an abstract class + +######### `SCOTT002` + +No valid cases were found. + +Raised when the target does not declare any usable nested case types. + +######### `SCOTT003` + +A nested case has an invalid shape. + +Raised when a case is not a: + +* partial class +* non-generic class +* non-abstract class + +######### `SCOTT004` + +A nested case has no accessible instance constructor. + +######### `SCOTT005` + +A nested case has an invalid relationship to the target. + +Raised when a case declares an unrelated base type. + +######### `SCOTT006` + +The target already declares a conflicting `Match` method. + +###### Generated files + +The generator emits: + +* `ScottEncodingAttribute.g.cs` +* one generated file per valid target, named from the target symbol + +The generated code enables nullable references with: + +```csharp +#nullable enable +``` + +###### Notes + +* Cases are processed in a stable order based on syntax location. +* The helper type is named `Module`. +* The helper type is generated as `static partial`. +* Matching delegates use fully qualified type names in generated code. +* The generated API preserves target type parameters and constraint clauses. + +###### Minimal example + +```csharp +[ScottEncoding] +public abstract partial class BoolLike +{ + public sealed partial class True + { + public True() \{ } + } + + public sealed partial class False + { + public False() \{ } + } +} +``` + +Usage: + +```csharp +BoolLike value = BoolLikeModule.True(); + +var result = value.Match( + @true => 1, + @false => 0); +``` + +::: + +### About +:::note + +Usage + + +1. You declare a union-like type as an abstract partial class and annotate it with ScottEncoding. + + +2. Inside it, you define each case as a sealed partial nested class (in this sample: Ok and None). + + +3. Your business logic returns one of those cases (Ok when save succeeds, None when it does not). + + +4. Consumer code can handle results either with normal C# pattern matching or with the generated functional matching API. + + + + + +2. What the generator adds + + +1. A Match contract on the parent union type, plus per-case implementations that dispatch to the correct handler. + + +2. A companion module with factory helpers to construct each case (Ok / None) without directly calling constructors. + + +3. A fluent matching flow (IfOk(...).IfNone(...)) built on top of Match. + + +4. A generated ScottEncodingAttribute definition, so the attribute is available at compile time. + + +::: + +## How to use + +### Example (source csproj, source files) + + + + + +This is the CSharp Project that references **ScottEncodingGenerator** +```xml showLineNumbers {16} + + + + Exe + net10.0 + enable + enable + + + + true + $(BaseIntermediateOutputPath)\GX + + + + + + + + + + +``` + + + + + + This is the use of **ScottEncodingGenerator** in *Program.cs* + +```csharp showLineNumbers +using UnionTypesDemo; + +Console.WriteLine("Save or not"); +ResultSave data = SaveToDatabase.Save(0); +var message= data switch +{ + ResultSave.Ok ok => $"Saved {ok.Value}", + ResultSave.None => "Not found", +}; +Console.WriteLine(message); +data = SaveToDatabase.Save(1); +message = data.Match( + + ok => $"Saved {ok.Value}", + none => "Not found" + ); +Console.WriteLine(message); + +``` + + + + + This is the use of **ScottEncodingGenerator** in *ResultSave.cs* + +```csharp showLineNumbers + + +namespace UnionTypesDemo; + + +[ScottEncoding] +public abstract partial class ResultSave +{ + + public sealed partial class Ok + { + public Ok(T value) => Value = value; + public T Value \{ get; } + } + + public sealed partial class None + { + public None() \{ } + } + +} + + +``` + + + + + This is the use of **ScottEncodingGenerator** in *SaveToDatabase.cs* + +```csharp showLineNumbers +namespace UnionTypesDemo; + +public class SaveToDatabase +{ + public static ResultSave Save(int i) + { + + if (i == 0) + { + return new ResultSave.None(); + } + return new ResultSave.Ok(i); + } +} + + + +``` + + + + +### Generated Files + +Those are taken from $(BaseIntermediateOutputPath)\GX + + + + +```csharp showLineNumbers +// +#nullable enable + +namespace UnionTypesDemo +{ + public abstract partial class ResultSave + { + public abstract TResult Match(global::System.Func.Ok, TResult> ok, global::System.Func.None, TResult> none); + + public sealed partial class Ok : global::UnionTypesDemo.ResultSave + { + public override TResult Match(global::System.Func.Ok, TResult> ok, global::System.Func.None, TResult> none) => ok(this); + } + + public sealed partial class None : global::UnionTypesDemo.ResultSave + { + public override TResult Match(global::System.Func.Ok, TResult> ok, global::System.Func.None, TResult> none) => none(this); + } + } + + public static partial class ResultSaveModule + { + public static global::UnionTypesDemo.ResultSave Ok(T value) => new global::UnionTypesDemo.ResultSave.Ok(value); + + public static global::UnionTypesDemo.ResultSave None() => new global::UnionTypesDemo.ResultSave.None(); + + public static MatchStep2 IfOk(this global::UnionTypesDemo.ResultSave value, global::System.Func.Ok, TResult> ok) => new(value, ok); + + public readonly struct MatchStep2 + { + private readonly global::UnionTypesDemo.ResultSave _value; + private readonly global::System.Func.Ok, TResult> _ok; + + public MatchStep2(global::UnionTypesDemo.ResultSave value, global::System.Func.Ok, TResult> ok) + { + _value = value; + _ok = ok; + } + + public TResult IfNone(global::System.Func.None, TResult> none) => _value.Match(_ok, none); + } + } +} + +``` + + + + +```csharp showLineNumbers +using System; + +[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false, Inherited = false)] +internal sealed class ScottEncodingAttribute : Attribute +{ +} +``` + + + + +## Useful + +### Download Example (.NET C#) + +:::tip + +[Download Example project ScottEncodingGenerator ](/sources/ScottEncodingGenerator.zip) + +::: + + +### Share ScottEncodingGenerator + + + +https://ignatandrei.github.io/RSCG_Examples/v2/docs/ScottEncodingGenerator + + + diff --git a/v2/rscg_examples_site/docs/RSCG-Examples/index.md b/v2/rscg_examples_site/docs/RSCG-Examples/index.md index 9ee899b26..077f13dfe 100644 --- a/v2/rscg_examples_site/docs/RSCG-Examples/index.md +++ b/v2/rscg_examples_site/docs/RSCG-Examples/index.md @@ -1,7 +1,7 @@ --- sidebar_position: 30 -title: 272 RSCG list by category -description: 272 RSCG list by category +title: 273 RSCG list by category +description: 273 RSCG list by category slug: /rscg-examples --- @@ -1043,7 +1043,7 @@ import DocCardList from '@theme/DocCardList'; ## FunctionalProgramming
- Expand FunctionalProgramming =>examples:17 + Expand FunctionalProgramming =>examples:18 @@ -1129,6 +1129,11 @@ import DocCardList from '@theme/DocCardList'; [Sundew.DiscriminatedUnions](/docs/Sundew.DiscriminatedUnions) + + + +[ScottEncodingGenerator](/docs/ScottEncodingGenerator) +
@@ -2080,6 +2085,8 @@ flowchart LR; FunctionalProgramming--> Sundew.DiscriminatedUnions((Sundew.DiscriminatedUnions)) + FunctionalProgramming--> ScottEncodingGenerator((ScottEncodingGenerator)) + Hangfire--> HangfireRecurringJob((HangfireRecurringJob)) Idempotency--> RSCG_idempotency((RSCG_idempotency)) diff --git a/v2/rscg_examples_site/docs/about.md b/v2/rscg_examples_site/docs/about.md index 6c8054f46..cbace812c 100644 --- a/v2/rscg_examples_site/docs/about.md +++ b/v2/rscg_examples_site/docs/about.md @@ -6,7 +6,7 @@ title: About ## Content You will find here code examples -of 272 Roslyn Source Code Generator (RSCG) +of 273 Roslyn Source Code Generator (RSCG) that can be useful for you. That means, you will write more elegant and concise code - even if the generators code is not always nice to look. ## Are those examples ready for production? diff --git a/v2/rscg_examples_site/docs/indexRSCG.md b/v2/rscg_examples_site/docs/indexRSCG.md index 5ed0b81e4..93c630289 100644 --- a/v2/rscg_examples_site/docs/indexRSCG.md +++ b/v2/rscg_examples_site/docs/indexRSCG.md @@ -7,9 +7,9 @@ slug: /List-of-RSCG import useBaseUrl from '@docusaurus/useBaseUrl'; -## 272 RSCG with examples in descending chronological order +## 273 RSCG with examples in descending chronological order -This is the list of 272 ( 16 from Microsoft) RSCG with examples +This is the list of 273 ( 16 from Microsoft) RSCG with examples [See by category](/docs/rscg-examples) [See as json](/exports/RSCG.json) [See as Excel](/exports/RSCG.xlsx) @@ -20,6 +20,7 @@ This is the list of 272 ( 16 from Microsoft) RSCG with examples | No | Name | Date | Category | | --------- | ----- | ---- | -------- | +|273| [ScottEncodingGenerator by Georgiy Petrov ](/docs/ScottEncodingGenerator)|2026-06-30 => 30 June 2026 | [FunctionalProgramming](/docs/Categories/FunctionalProgramming) | |272| [AlephMapper by Yevhen Cherkes ](/docs/AlephMapper)|2026-06-29 => 29 June 2026 | [Database](/docs/Categories/Database) | |271| [TypedStateBuilder.Generator by Georgiy Petrov ](/docs/TypedStateBuilder.Generator)|2026-05-16 => 16 May 2026 | [Builder](/docs/Categories/Builder) | |270| [AssemblyMetadata.Generators by LoreSoft ](/docs/AssemblyMetadata.Generators)|2026-05-15 => 15 May 2026 | [EnhancementProject](/docs/Categories/EnhancementProject) | diff --git a/v2/rscg_examples_site/src/components/HomepageFeatures/index.js b/v2/rscg_examples_site/src/components/HomepageFeatures/index.js index 23ee71dc2..efb5ae47c 100644 --- a/v2/rscg_examples_site/src/components/HomepageFeatures/index.js +++ b/v2/rscg_examples_site/src/components/HomepageFeatures/index.js @@ -4,7 +4,7 @@ import styles from './styles.module.css'; const FeatureList = [ { -title: '272 Examples (16 from MSFT)', +title: '273 Examples (16 from MSFT)', Svg: require('@site/static/img/undraw_docusaurus_mountain.svg').default, description: ( <> diff --git a/v2/rscg_examples_site/static/exports/RSCG.json b/v2/rscg_examples_site/static/exports/RSCG.json index e681a8851..6b6fc2682 100644 --- a/v2/rscg_examples_site/static/exports/RSCG.json +++ b/v2/rscg_examples_site/static/exports/RSCG.json @@ -2177,6 +2177,14 @@ "Source": "https://github.com/Raffinert/AlephMapper", "Category": "Database", "AddedOn": "2026-06-29T00:00:00" + }, + { + "Name": "ScottEncodingGenerator", + "Link": "https://ignatandrei.github.io/RSCG_Examples/v2/docs/ScottEncodingGenerator", + "NuGet": "https://www.nuget.org/packages/ScottEncodingGenerator/", + "Source": "https://github.com/Georgiy-Petrov/ScottEncodingGenerator", + "Category": "FunctionalProgramming", + "AddedOn": "2026-06-30T00:00:00" } ] } \ No newline at end of file diff --git a/v2/rscg_examples_site/static/exports/RSCG.xlsx b/v2/rscg_examples_site/static/exports/RSCG.xlsx index 07cb1215e..c19d791e9 100644 Binary files a/v2/rscg_examples_site/static/exports/RSCG.xlsx and b/v2/rscg_examples_site/static/exports/RSCG.xlsx differ diff --git a/v2/rscg_examples_site/static/sources/AlephMapper.zip b/v2/rscg_examples_site/static/sources/AlephMapper.zip index f7f1cda82..dd80624f3 100644 Binary files a/v2/rscg_examples_site/static/sources/AlephMapper.zip and b/v2/rscg_examples_site/static/sources/AlephMapper.zip differ diff --git a/v2/rscg_examples_site/static/sources/ScottEncodingGenerator.zip b/v2/rscg_examples_site/static/sources/ScottEncodingGenerator.zip new file mode 100644 index 000000000..390f5b633 Binary files /dev/null and b/v2/rscg_examples_site/static/sources/ScottEncodingGenerator.zip differ