Skip to content

Commit

Permalink
IncrementalGeneraotr and various fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
neuecc committed Jan 7, 2025
1 parent 70c5af9 commit 00c2e3f
Show file tree
Hide file tree
Showing 6 changed files with 604 additions and 622 deletions.
53 changes: 12 additions & 41 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ NuGet: [UnitGenerator](https://www.nuget.org/packages/UnitGenerator)
Install-Package UnitGenerator
```

Execute in Unity Game Engine is also supported, please see the [Unity](#use-for-unity) section for details.

## Introduction

For example, Identifier, UserId is comparable only to UserId, and cannot be assigned to any other type. Also, arithmetic operations are not allowed.
Expand All @@ -18,16 +20,15 @@ For example, Identifier, UserId is comparable only to UserId, and cannot be assi
using UnitGenerator;

[UnitOf(typeof(int))]
public readonly partial struct UserId { }
public readonly partial struct UserId; { }
```

or when using C#11 and NET7 you can use

```csharp
using UnitGenerator;

[UnitOf<int>]
public readonly partial struct UserId { }
[UnitOf<int>] public readonly partial struct UserId;
```

will generates
Expand Down Expand Up @@ -63,8 +64,8 @@ public readonly partial struct UserId : IEquatable<UserId>
However, Hp in games, should not be allowed to be assigned to other types, but should support arithmetic operations with int. For example double heal = `target.Hp = Hp.Min(target.Hp * 2, target.MaxHp)`.

```csharp
[UnitOf(typeof(int), UnitGenerateOptions.ArithmeticOperator | UnitGenerateOptions.ValueArithmeticOperator | UnitGenerateOptions.Comparable | UnitGenerateOptions.MinMaxMethod)]
public readonly partial struct Hp { }
[UnitOf<int>(UnitGenerateOptions.ArithmeticOperator | UnitGenerateOptions.ValueArithmeticOperator | UnitGenerateOptions.Comparable | UnitGenerateOptions.MinMaxMethod)]
public readonly partial struct Hp;

// -- generates
Expand Down Expand Up @@ -162,11 +163,11 @@ enum UnitGenerateOptions

UnitGenerateOptions has some serializer support. For example, a result like `Serialize(userId) => { Value = 1111 }` is awful. The value-object should be serialized natively, i.e. `Serialize(useId) => 1111`, and should be able to be added directly to a database, etc.

Currently UnitGenerator supports [MessagePack for C#](https://github.com/neuecc/MessagePack-CSharp), System.Text.Json(JsonSerializer), [Dapper](https://github.com/StackExchange/Dapper) and EntityFrameworkCore.
Currently UnitGenerator supports [MessagePack for C#](https://github.com/MessagePack-CSharp/MessagePack-CSharp), System.Text.Json(JsonSerializer), [Dapper](https://github.com/StackExchange/Dapper) and EntityFrameworkCore.

```csharp
[UnitOf(typeof(int), UnitGenerateOptions.MessagePackFormatter)]
public readonly partial struct UserId { }
[UnitOf<int>(UnitGenerateOptions.MessagePackFormatter)]
public readonly partial struct UserId;

// -- generates
Expand Down Expand Up @@ -556,41 +557,11 @@ builder.HasConversion(new UserId.UserIdValueConverter());

## Use for Unity

C# Source Generator feature is rely on C# 9.0. If you are using Unity 2021.2, that supports [Source Generators](https://docs.unity3d.com/2021.2/Documentation/Manual/roslyn-analyzers.html). Add the `UnitGenerator.dll` from the [releases page](https://github.com/Cysharp/UnitGenerator/releases), disable Any Platform, disable Include all platforms and set label as `RoslynAnalyzer`.
It works in Unity Editor however does not work on IDE because Unity does not generate analyzer reference to `.csproj`. We provides [CsprojModifer](https://github.com/Cysharp/CsprojModifier) to analyzer support, uses `Add analyzer references to generated .csproj` supports both IDE and Unity Editor.
Unity(2020) does not support C# 9.0 so can not use directly. However, C# Source Genertor supports output source as file.

1. Create `UnitSourceGen.csproj`.

```xml
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
Minimum supported Unity version is `2022.3.12f1`.

<!-- add this two lines and configure output path -->
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>$(ProjectDir)..\Generated</CompilerGeneratedFilesOutputPath>
</PropertyGroup>

<ItemGroup>
<!-- reference UnitGenerator -->
<PackageReference Include="UnitGenerator" Version="1.0.0" />

<!-- add target sources path from Unity -->
<Compile Include="..\MyUnity\Assets\Scripts\Models\**\*.cs" />
</ItemGroup>
</Project>
```

2. install [.NET SDK](https://dotnet.microsoft.com/download) and run this command.
```
dotnet build UnitSourceGen.csproj
```
The easiest way is to install `UnitGenerator` from NuGet using [NuGetForUnity](https://github.com/GlitchEnzo/NuGetForUnity).
File will be generated under `UnitGenerator\UnitGenerator.SourceGenerator\*.Generated.cs`. `UnitOfAttribute` is also included in generated folder, so at first, run build command and get attribute to configure.
Alternatively, you can download `UnitGenerator.dll` from the [releases page](https://github.com/Cysharp/UnitGenerator/releases) page and set it up as a `RoslynAnalyzer` to make it work.
License
---
Expand Down
6 changes: 5 additions & 1 deletion sandbox/ConsoleApp/AllPrimitives.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Linq;
using System.Numerics;
Expand All @@ -11,14 +12,17 @@

namespace ConsoleApp
{



[UnitOf(typeof(int), UnitGenerateOptions.Normalize | UnitGenerateOptions.ParseMethod | UnitGenerateOptions.MinMaxMethod | UnitGenerateOptions.ArithmeticOperator | UnitGenerateOptions.ValueArithmeticOperator | UnitGenerateOptions.Comparable | UnitGenerateOptions.Validate | UnitGenerateOptions.JsonConverter | UnitGenerateOptions.MessagePackFormatter | UnitGenerateOptions.DapperTypeHandler | UnitGenerateOptions.EntityFrameworkValueConverter | UnitGenerateOptions.JsonConverterDictionaryKeySupport)]
public readonly partial struct A
{
private partial void Normalize(ref int value)
{
value = Math.Clamp(value, 0, 100);
}

private partial void Validate()
{
_ = AsPrimitive();
Expand Down
33 changes: 31 additions & 2 deletions sandbox/ConsoleApp/Program.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
using Sample;
//using Sample;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Text;
using System.Text.Json;
Expand All @@ -19,12 +20,40 @@

Console.WriteLine(json);





[UnitOf<int>] public readonly partial struct MyId;


public readonly struct MyParsable : IParsable<MyParsable>
{
public static MyParsable Parse(string s)
=> throw new NotImplementedException();

public static bool TryParse([NotNullWhen(true)] string? s, [MaybeNullWhen(false)] out MyParsable result)
=> throw new NotImplementedException();

public static MyParsable Parse(string s, IFormatProvider? provider)
=> throw new NotImplementedException();

public static bool TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, [MaybeNullWhen(false)] out MyParsable result)
=> throw new NotImplementedException();
}

[UnitOf(typeof(MyParsable), UnitGenerateOptions.ParseMethod)]
public readonly partial struct StructInOtherLib
{
public static void Test()
=> StructInOtherLib.Parse("");
}

[UnitOf(typeof(ulong), UnitGenerateOptions.ArithmeticOperator)]
public readonly partial struct Money
{
}


[UnitOf(typeof(int))]
public readonly partial struct NoNamespace
{
Expand Down
24 changes: 24 additions & 0 deletions src/UnitGenerator/IgnoreEquality.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using System;

namespace UnitGenerator;

public readonly struct IgnoreEquality<T>(T value) : IEquatable<IgnoreEquality<T>>
{
public readonly T Value => value;

public static implicit operator IgnoreEquality<T>(T value)
{
return new IgnoreEquality<T>(value);
}

public static implicit operator T(IgnoreEquality<T> value)
{
return value.Value;
}

public bool Equals(IgnoreEquality<T> other)
{
// always true to ignore equality check.
return true;
}
}
Loading

0 comments on commit 00c2e3f

Please sign in to comment.