Skip to content

Commit

Permalink
[c#] add support for init-only setters on generated classes
Browse files Browse the repository at this point in the history
  • Loading branch information
enioluwas committed Jun 26, 2022
1 parent 79de73c commit 61a637d
Show file tree
Hide file tree
Showing 9 changed files with 54 additions and 3 deletions.
2 changes: 2 additions & 0 deletions compiler/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ csCodegen options@Cs {..} = do
else csTypeMapping
fieldMapping = if readonly_properties
then ReadOnlyProperties
else if init_only_properties
then InitOnlyProperties
else if fields
then PublicFields
else Properties
Expand Down
4 changes: 3 additions & 1 deletion compiler/Options.hs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ data Options
, namespace :: [String]
, collection_interfaces :: Bool
, readonly_properties :: Bool
, init_only_properties :: Bool
, fields :: Bool
, jobs :: Maybe Int
, no_banner :: Bool
Expand Down Expand Up @@ -106,9 +107,10 @@ cs :: Options
cs = Cs
{ collection_interfaces = def &= name "c" &= help "Use interfaces rather than concrete collection types"
, readonly_properties = def &= name "r" &= help "Generate private property setters"
, init_only_properties = def &= name "init-only" &= help "Generate init-only property setters"
, fields = def &= name "f" &= help "Generate public fields rather than properties"
, structs_enabled = True &= explicit &= name "structs" &= help "Generate C# types for Bond structs and enums (true by default, use \"--structs=false\" to disable)"
, constructor_parameters = def &= explicit &= name "preview-constructor-parameters" &= help "PREVIEW FEATURE: Generate a constructor that takes all the fields as parameters. Typically used with readonly-properties."
, constructor_parameters = def &= explicit &= name "preview-constructor-parameters" &= help "PREVIEW FEATURE: Generate a constructor that takes all the fields as parameters. Typically used with readonly-properties or init-only-properties."
} &=
name "c#" &=
help "Generate C# code"
Expand Down
4 changes: 3 additions & 1 deletion compiler/src/Language/Bond/Codegen/Cs/Types_cs.hs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ data StructMapping =
data FieldMapping =
PublicFields | -- ^ public fields
Properties | -- ^ auto-properties
ReadOnlyProperties -- ^ auto-properties with private setter
ReadOnlyProperties | -- ^ auto-properties with private setter
InitOnlyProperties -- ^ auto-properties with init-only setter
deriving Eq

-- | Options for how constructors should be generated.
Expand Down Expand Up @@ -186,6 +187,7 @@ namespace #{csNamespace}
PublicFields -> [lt|#{optional fieldInitializer $ csDefault f};|]
Properties -> [lt| { get; set; }|]
ReadOnlyProperties -> [lt| { get; private set; }|]
InitOnlyProperties -> [lt| { get; init; }|]
fieldInitializer x = [lt| = #{x}|]
new = if isBaseField fieldName structBase then "new " else "" :: String

Expand Down
14 changes: 14 additions & 0 deletions compiler/tests/TestMain.hs
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,13 @@ tests = testGroup "Compiler tests"
]
"complex_inheritance"
"constructor-parameters"
, verifyCodegenVariation
[ "c#"
, "--preview-constructor-parameters"
, "--init-only-properties"
]
"complex_inheritance"
"constructor-parameters"
, verifyCodegenVariation
[ "c#"
, "--preview-constructor-parameters"
Expand Down Expand Up @@ -180,6 +187,13 @@ tests = testGroup "Compiler tests"
]
"empty_struct"
"constructor-parameters"
, verifyCodegenVariation
[ "c#"
, "--preview-constructor-parameters"
, "--init-only-properties"
]
"empty_struct"
"constructor-parameters"
]
, testGroup "Java"
[ verifyJavaCodegen "attributes"
Expand Down
2 changes: 2 additions & 0 deletions compiler/tests/Tests/Codegen.hs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ verifyFiles options baseName variation =
verify = verifyFile options baseName
fieldMapping Cs {..} = if readonly_properties
then ReadOnlyProperties
else if init_only_properties
then InitOnlyProperties
else if fields
then PublicFields
else Properties
Expand Down
5 changes: 5 additions & 0 deletions cs/nuget/bond.csharp.test.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,9 @@
<Options>$(BondOptions) --using="DateTime=System.DateTime"</Options>
</BondCodegen>
</ItemGroup>
<ItemGroup Condition="$(TargetFramework.StartsWith('net5.0')) or $(TargetFramework.StartsWith('net6.0'))">
<BondCodegen Update="..\test\core\InitOnly.bond">
<Options>$(BondOptions) --init-only-properties</Options>
</BondCodegen>
</ItemGroup>
</Project>
14 changes: 14 additions & 0 deletions cs/test/core/SerializationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,20 @@ public void ReadonlySimpleContainers()
TestSerialization<Readonly.SimpleContainers>();
}

#if NET5_0_OR_GREATER
[Test]
public void InitOnlyBasicTypes()
{
TestSerialization<InitOnly.BasicTypes>();
}

[Test]
public void InitOnlySimpleContainers()
{
TestSerialization<InitOnly.SimpleContainers>();
}
#endif

[Test]
public void Nested()
{
Expand Down
5 changes: 5 additions & 0 deletions cs/test/coreNS10/CoreNS10.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@
<Options Condition=" '$(Configuration)' != 'Fields' ">$(BondOptions) --readonly-properties</Options>
<Options Condition=" '$(Configuration)' == 'Fields' ">--readonly-properties --collection-interfaces</Options>
</BondCodegen>
<BondCodegen Update="InitOnly.bond">
<Options Condition=" '$(Configuration)' != 'Fields' ">$(BondOptions) --init-only-properties</Options>
<Options Condition=" '$(Configuration)' == 'Fields' ">--init-only-properties --collection-interfaces</Options>
</BondCodegen>
<BondCodegen Include="..\core\Containers.bond">
<Options Condition=" '$(Configuration)' != 'Fields' ">$(BondOptions) --collection-interfaces</Options>
<Options Condition=" '$(Configuration)' == 'Fields' ">--fields</Options>
Expand All @@ -53,6 +57,7 @@
<Compile Include="$(IntermediateOutputPath)\NamespaceConflict_types.cs" Condition="False" />
<Compile Include="$(IntermediateOutputPath)\NamespaceConflictBond_types.cs" Condition="False" />
<Compile Include="$(IntermediateOutputPath)\ReadOnly_types.cs" Condition="False" />
<Compile Include="$(IntermediateOutputPath)\InitOnly_types.cs" Condition="False" />
<Compile Include="$(IntermediateOutputPath)\UnitTest_types.cs" Condition="False" />
<!-- End Resharper Workaround -->
</ItemGroup>
Expand Down
7 changes: 6 additions & 1 deletion doc/src/bond_cs.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,11 +127,16 @@ Schema fields are represented by properties with public getter and private
setter and initialized to the default values in the default constructor.
Classes with read-only properties are fully supported by all Bond APIs.

`--init-only-properties`

Schema fields are represented by properties with public getter and
[C# 9 init-only setter](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/init) and initialized to the default values in the default constructor. Classes with init-only properties are fully supported by all Bond APIs.

`--preview-constructor-parameters`

A constructor is generated with a parameter to initialize each of the schema
fields. This option is typically used in conjunction with
`--readonly-properties`. This functionailty is in preview and may change.
`--readonly-properties` or `--init-only-properties`. This functionailty is in preview and may change.

`--collection-interfaces`

Expand Down

0 comments on commit 61a637d

Please sign in to comment.